From 268beb4ebc1e5b8d4ad715b71cd64a0944073a87 Mon Sep 17 00:00:00 2001
From: wujian <14790700720@163.com>
Date: 星期四, 22 二月 2024 08:56:17 +0800
Subject: [PATCH] first commit

---
 jcdm-ui/src/views/main/da/passingStationCollection/index.vue                                                              |  370 
 jcdm-system/src/main/java/com/jcdm/system/domain/vo/MetaVo.java                                                           |  106 
 jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/service/impl/DaOpcuaConfigServiceImpl.java                           |   94 
 jcdm-ui/src/utils/jsencrypt.js                                                                                            |   30 
 jcdm-main/src/main/resources/mapper/bs/beatSetting/BsBeatSettingMapper.xml                                                |  103 
 jcdm-ui/src/assets/icons/svg/money.svg                                                                                    |    1 
 jcdm-ui/src/views/monitor/cache/index.vue                                                                                 |  148 
 jcdm-framework/src/main/java/com/jcdm/framework/config/ResourcesConfig.java                                               |   73 
 jcdm-admin/src/main/java/com/jcdm/web/controller/monitor/ServerController.java                                            |   27 
 jcdm-main/src/main/java/com/jcdm/main/bs/formula/domain/BsFormulaInfo.java                                                |  176 
 jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysProfileController.java                                         |  137 
 jcdm-common/src/main/java/com/jcdm/common/annotation/Excels.java                                                          |   18 
 jcdm-ui/src/views/main/em/equipmentStatus/index.vue                                                                       |  356 
 jcdm-system/src/main/java/com/jcdm/system/mapper/SysRoleDeptMapper.java                                                   |   44 
 jcdm-ui/src/assets/icons/svg/button.svg                                                                                   |    1 
 jcdm-ui/src/assets/icons/svg/exit-fullscreen.svg                                                                          |    1 
 jcdm-ui/src/api/main/om/workReport/workReport.js                                                                          |   44 
 jcdm-generator/src/main/java/com/jcdm/generator/domain/GenTable.java                                                      |  385 
 jcdm-ui/src/views/dashboard/LineChart.vue                                                                                 |  135 
 jcdm-ui/src/plugins/download.js                                                                                           |   79 
 jcdm-ui/src/assets/icons/svg/excel.svg                                                                                    |    1 
 jcdm-ui/src/assets/icons/svg/education.svg                                                                                |    1 
 jcdm-ui/public/robots.txt                                                                                                 |    2 
 jcdm-ui/src/layout/mixin/ResizeHandler.js                                                                                 |   45 
 jcdm-framework/src/main/java/com/jcdm/framework/interceptor/impl/SameUrlDataInterceptor.java                              |  110 
 jcdm-ui/src/directive/dialog/drag.js                                                                                      |   64 
 jcdm-common/src/main/java/com/jcdm/common/exception/file/FileException.java                                               |   19 
 jcdm-ui/src/assets/images/profile.jpg                                                                                     |    0 
 jcdm-ui/src/components/RightPanel/index.vue                                                                               |  106 
 jcdm-ui/src/main.js                                                                                                       |  103 
 jcdm-ui/src/assets/styles/ruoyi.scss                                                                                      |  291 
 jcdm-generator/src/main/resources/vm/vue/index.vue.vm                                                                     |  615 
 jcdm-main/src/main/java/com/jcdm/main/bs/technologyRouteChild/controller/BsTechnologyRouteChildInfoController.java        |  104 
 jcdm-ui/src/layout/components/TagsView/ScrollPane.vue                                                                     |   94 
 jcdm-ui/src/utils/dict/DictData.js                                                                                        |   13 
 jcdm-system/src/main/java/com/jcdm/system/service/impl/SysRoleServiceImpl.java                                            |  424 
 jcdm-framework/src/main/java/com/jcdm/framework/config/ServerConfig.java                                                  |   32 
 jcdm-main/src/main/java/com/jcdm/main/em/equipmentStatus/service/impl/EmEquipmentStatusServiceImpl.java                   |   95 
 jcdm-system/src/main/java/com/jcdm/system/mapper/SysNoticeMapper.java                                                     |   60 
 jcdm-framework/src/main/java/com/jcdm/framework/web/exception/GlobalExceptionHandler.java                                 |  138 
 jcdm-framework/src/main/java/com/jcdm/framework/websocket/PostController.java                                             |   31 
 jcdm-generator/src/main/java/com/jcdm/generator/domain/GenTableColumn.java                                                |  373 
 jcdm-framework/src/main/java/com/jcdm/framework/manager/ShutdownManager.java                                              |   39 
 jcdm-main/src/main/java/com/jcdm/main/bs/productBomChild/service/IBsProductBomChildInfoService.java                       |   63 
 jcdm-generator/src/main/java/com/jcdm/generator/service/GenTableServiceImpl.java                                          |  521 
 jcdm-common/src/main/java/com/jcdm/common/utils/file/MimeTypeUtils.java                                                   |   59 
 jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/service/IDaOpcuaConfigService.java                                   |   62 
 jcdm-ui/src/assets/icons/svg/list.svg                                                                                     |    1 
 jcdm-ui/src/views/tool/build/RightPanel.vue                                                                               |  946 
 jcdm-main/src/main/java/com/jcdm/main/bs/lineInfo/service/IBsLineInfoService.java                                         |   61 
 jcdm-ui/src/components/IconSelect/requireIcons.js                                                                         |   11 
 jcdm-ui/src/views/error/401.vue                                                                                           |   88 
 jcdm-ui/src/assets/icons/svgo.yml                                                                                         |   22 
 jcdm-main/src/main/java/com/jcdm/main/bs/processes/service/IBsProcessesInfoService.java                                   |   62 
 jcdm-ui/src/assets/images/dark.svg                                                                                        |   39 
 bin/run.bat                                                                                                               |   14 
 jcdm-common/pom.xml                                                                                                       |  145 
 jcdm-main/src/main/java/com/jcdm/main/em/equipmentAlarm/domain/EmEquipmentAlarm.java                                      |  257 
 bin/package.bat                                                                                                           |   12 
 jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysMenuController.java                                            |  142 
 jcdm-ui/src/router/directives.js                                                                                          |   74 
 jcdm-admin/src/main/resources/application-druid.yml                                                                       |   72 
 jcdm-admin/src/main/java/com/jcdm/web/controller/common/CommonController.java                                             |  163 
 jcdm-system/src/main/java/com/jcdm/system/mapper/SysRoleMapper.java                                                       |  107 
 jcdm-ui/src/store/modules/settings.js                                                                                     |   42 
 jcdm-ui/src/assets/icons/svg/edit.svg                                                                                     |    1 
 jcdm-admin/src/main/java/com/jcdm/web/controller/tool/TestController.java                                                 |  183 
 jcdm-system/src/main/resources/mapper/system/SysOperLogMapper.xml                                                         |   87 
 jcdm-main/src/main/resources/mapper/om/workReport/OmWorkReportMapper.xml                                                  |  128 
 jcdm-common/src/main/java/com/jcdm/common/exception/user/BlackListException.java                                          |   16 
 jcdm-quartz/src/main/resources/mapper/quartz/SysJobMapper.xml                                                             |  111 
 jcdm-framework/src/main/java/com/jcdm/framework/aspectj/RateLimiterAspect.java                                            |   89 
 jcdm-ui/src/assets/styles/mixin.scss                                                                                      |   66 
 jcdm-system/src/main/java/com/jcdm/system/service/impl/SysNoticeServiceImpl.java                                          |   92 
 jcdm-main/src/main/java/com/jcdm/main/em/equipmentArchives/domain/EmEquipmentArchives.java                                |  287 
 jcdm-ui/src/components/itemSelect/single.vue                                                                              |  210 
 jcdm-ui/src/assets/icons/svg/email.svg                                                                                    |    1 
 jcdm-ui/src/api/main/bs/technologyRoute/technologyRoute.js                                                                |   52 
 jcdm-main/src/main/resources/mapper/da/collectionParamConf/DaCollectionParamConfMapper.xml                                |  157 
 jcdm-ui/src/views/main/rm/repairRecord/index.vue                                                                          |  337 
 jcdm-common/src/main/java/com/jcdm/common/core/domain/AjaxResult.java                                                     |  216 
 jcdm-framework/src/main/java/com/jcdm/framework/web/domain/server/Cpu.java                                                |  101 
 jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/service/IDaPassingStationCollectionService.java         |   72 
 jcdm-ui/src/views/main/bs/workshop/index.vue                                                                              |  335 
 jcdm-main/src/main/java/com/jcdm/main/bs/lineInfo/mapper/BsLineInfoMapper.java                                            |   61 
 jcdm-main/src/main/java/com/jcdm/main/om/productionOrde/mapper/OmProductionOrdeInfoMapper.java                            |   64 
 jcdm-common/src/main/java/com/jcdm/common/enums/BusinessStatus.java                                                       |   20 
 jcdm-main/src/main/java/com/jcdm/main/bs/productBom/controller/BsProductBomInfoController.java                            |  110 
 jcdm-system/src/main/java/com/jcdm/system/service/ISysDeptService.java                                                    |  124 
 jcdm-ui/src/views/login.vue                                                                                               |  244 
 jcdm-ui/src/views/main/em/equipmentArchives/index.vue                                                                     |  436 
 jcdm-quartz/src/main/java/com/jcdm/quartz/util/CronUtils.java                                                             |   63 
 jcdm-ui/src/api/main/om/productionOrde/productionOrde.js                                                                  |   52 
 jcdm-ui/src/views/monitor/server/index.vue                                                                                |  207 
 jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysNoticeController.java                                          |   91 
 jcdm-system/src/main/java/com/jcdm/system/service/ISysRoleService.java                                                    |  173 
 jcdm-ui/src/components/Editor/index.vue                                                                                   |  274 
 jcdm-ui/src/assets/icons/svg/clipboard.svg                                                                                |    1 
 jcdm-common/src/main/java/com/jcdm/common/enums/OperatorType.java                                                         |   24 
 jcdm-ui/bin/package.bat                                                                                                   |   12 
 jcdm-ui/src/utils/ruoyi.js                                                                                                |  232 
 jcdm-ui/src/utils/scroll-to.js                                                                                            |   58 
 jcdm-common/src/main/java/com/jcdm/common/enums/BusinessType.java                                                         |   59 
 jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/domain/DaPassingStationCollection.java                  |  302 
 jcdm-framework/src/main/java/com/jcdm/framework/web/service/SysRegisterService.java                                       |  115 
 jcdm-main/src/main/resources/mapper/sc/stationConf/ScStationConfMapper.xml                                                |  114 
 jcdm-ui/src/views/system/dept/index.vue                                                                                   |  340 
 jcdm-framework/src/main/java/com/jcdm/framework/security/handle/AuthenticationEntryPointImpl.java                         |   34 
 jcdm-ui/src/views/main/bs/beatSetting/index.vue                                                                           |  336 
 jcdm-generator/src/main/java/com/jcdm/generator/mapper/GenTableMapper.java                                                |   83 
 jcdm-ui/src/assets/images/login-background1.png                                                                           |    0 
 jcdm-framework/src/main/java/com/jcdm/framework/web/domain/server/Jvm.java                                                |  130 
 jcdm-common/src/main/java/com/jcdm/common/annotation/Anonymous.java                                                       |   19 
 jcdm-ui/src/api/system/role.js                                                                                            |  119 
 jcdm-quartz/src/main/java/com/jcdm/quartz/config/ScheduleConfig.java                                                      |   57 
 jcdm-ui/src/api/main/rm/repairRecord/repairRecord.js                                                                      |   44 
 jcdm-framework/src/main/java/com/jcdm/framework/config/ApplicationConfig.java                                             |   30 
 jcdm-ui/src/utils/generator/icon.json                                                                                     |    1 
 jcdm-system/src/main/java/com/jcdm/system/service/impl/SysDictDataServiceImpl.java                                        |  111 
 jcdm-ui/src/assets/icons/svg/eye-open.svg                                                                                 |    1 
 jcdm-ui/src/layout/components/Sidebar/Link.vue                                                                            |   43 
 jcdm-common/src/main/java/com/jcdm/common/utils/file/FileUploadUtils.java                                                 |  232 
 jcdm-system/src/main/resources/mapper/system/SysUserPostMapper.xml                                                        |   34 
 jcdm-ui/src/components/DictTag/index.vue                                                                                  |   89 
 jcdm-common/src/main/java/com/jcdm/common/enums/UserStatus.java                                                           |   30 
 jcdm-ui/src/assets/icons/svg/documentation.svg                                                                            |    1 
 jcdm-ui/src/assets/icons/svg/swagger.svg                                                                                  |    1 
 jcdm-main/src/main/java/com/jcdm/main/rm/repairRecord/service/IRmRepairRecordService.java                                 |   61 
 jcdm-system/src/main/resources/mapper/system/SysUserRoleMapper.xml                                                        |   44 
 jcdm-ui/src/views/system/user/profile/index.vue                                                                           |   91 
 jcdm-ui/src/assets/icons/svg/color.svg                                                                                    |    1 
 jcdm-ui/src/assets/icons/svg/time.svg                                                                                     |    1 
 jcdm-common/src/main/java/com/jcdm/common/enums/HttpMethod.java                                                           |   36 
 jcdm-common/src/main/java/com/jcdm/common/utils/ExceptionUtil.java                                                        |   39 
 jcdm-ui/src/components/RuoYi/Doc/index.vue                                                                                |   21 
 jcdm-ui/src/api/menu.js                                                                                                   |    9 
 jcdm-ui/src/views/components/icons/index.vue                                                                              |   87 
 jcdm-ui/src/views/system/dict/data.vue                                                                                    |  402 
 jcdm-quartz/src/main/java/com/jcdm/quartz/util/QuartzJobExecution.java                                                    |   19 
 jcdm-common/src/main/java/com/jcdm/common/exception/GlobalException.java                                                  |   58 
 jcdm-ui/src/views/index.vue                                                                                               |   96 
 jcdm-common/src/main/java/com/jcdm/common/exception/user/CaptchaException.java                                            |   16 
 jcdm-ui/src/utils/auth.js                                                                                                 |   15 
 jcdm-ui/src/views/dashboard/RaddarChart.vue                                                                               |  116 
 jcdm-ui/src/layout/components/Navbar.vue                                                                                  |  192 
 jcdm-ui/src/components/Crontab/index.vue                                                                                  |  430 
 jcdm-quartz/src/main/java/com/jcdm/quartz/util/QuartzDisallowConcurrentExecution.java                                     |   21 
 jcdm-main/src/main/java/com/jcdm/main/bs/processes/domain/BsProcessesInfo.java                                            |  217 
 jcdm-common/src/main/java/com/jcdm/common/core/controller/BaseController.java                                             |  202 
 jcdm-system/src/main/java/com/jcdm/system/mapper/SysLogininforMapper.java                                                 |   42 
 jcdm-main/src/main/java/com/jcdm/main/sc/stationConf/domain/ScStationConf.java                                            |  193 
 jcdm-ui/src/assets/icons/svg/eye.svg                                                                                      |    1 
 jcdm-ui/src/directive/module/clipboard.js                                                                                 |   54 
 jcdm-ui/src/api/monitor/operlog.js                                                                                        |   26 
 jcdm-ui/src/layout/components/TagsView/index.vue                                                                          |  332 
 jcdm-ui/src/utils/generator/render.js                                                                                     |  126 
 jcdm-ui/src/views/system/user/index.vue                                                                                   |  670 
 jcdm-ui/src/directive/index.js                                                                                            |   23 
 jcdm-system/src/main/java/com/jcdm/system/service/ISysUserService.java                                                    |  206 
 jcdm-ui/src/views/dashboard/mixins/resize.js                                                                              |   56 
 jcdm-main/src/main/java/com/jcdm/main/rm/repairData/mapper/RmRepairDataMapper.java                                        |   61 
 jcdm-main/src/main/java/com/jcdm/main/bs/material/controller/BsMaterialInfoController.java                                |  111 
 jcdm-ui/src/assets/styles/element-ui.scss                                                                                 |   92 
 jcdm-common/src/main/java/com/jcdm/common/exception/DemoModeException.java                                                |   15 
 jcdm-main/src/main/java/com/jcdm/main/em/equipmentStatus/mapper/EmEquipmentStatusMapper.java                              |   61 
 jcdm-common/src/main/java/com/jcdm/common/utils/html/EscapeUtil.java                                                      |  167 
 jcdm-quartz/src/main/java/com/jcdm/quartz/domain/SysJob.java                                                              |  171 
 jcdm-ui/src/assets/icons/svg/qq.svg                                                                                       |    1 
 jcdm-main/src/main/java/com/jcdm/main/da/paramCollection/domain/DaParamCollection.java                                    |  317 
 jcdm-common/src/main/java/com/jcdm/common/utils/html/HTMLFilter.java                                                      |  570 
 jcdm-ui/src/views/main/da/opcuaconfig/index.vue                                                                           |  426 
 jcdm-common/src/main/java/com/jcdm/common/core/page/PageDomain.java                                                       |  101 
 jcdm-system/src/main/java/com/jcdm/system/mapper/SysUserPostMapper.java                                                   |   44 
 jcdm-ui/src/components/RightToolbar/index.vue                                                                             |  129 
 jcdm-ui/src/views/main/sc/stationConf/index.vue                                                                           |  342 
 jcdm-ui/.env.development                                                                                                  |   11 
 jcdm-framework/src/main/java/com/jcdm/framework/aspectj/DataScopeAspect.java                                              |  174 
 jcdm-ui/public/html/ie.html                                                                                               |   46 
 jcdm-ui/src/settings.js                                                                                                   |   44 
 jcdm-ui/src/api/monitor/logininfor.js                                                                                     |   34 
 jcdm-main/src/main/java/com/jcdm/main/da/collectionParamConf/domain/DaCollectionParamConf.java                            |  343 
 jcdm-system/src/main/java/com/jcdm/system/mapper/SysConfigMapper.java                                                     |   76 
 jcdm-ui/src/store/modules/app.js                                                                                          |   66 
 jcdm-ui/src/assets/icons/svg/tab.svg                                                                                      |    1 
 jcdm-main/src/main/resources/mapper/da/opcuaconfig/DaOpcuaConfigMapper.xml                                                |   86 
 jcdm-common/src/main/java/com/jcdm/common/xss/XssValidator.java                                                           |   34 
 jcdm-main/src/main/java/com/jcdm/main/bs/productBom/service/impl/BsProductBomInfoServiceImpl.java                         |   97 
 jcdm-system/src/main/java/com/jcdm/system/mapper/SysDeptMapper.java                                                       |  118 
 jcdm-main/pom.xml                                                                                                         |  101 
 jcdm-framework/src/main/java/com/jcdm/framework/web/domain/Server.java                                                    |  240 
 jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/mapper/DaOpcuaConfigMapper.java                                      |   62 
 jcdm-ui/src/utils/dict/DictOptions.js                                                                                     |   51 
 jcdm-ui/src/assets/images/login-background.png                                                                            |    0 
 jcdm-quartz/pom.xml                                                                                                       |   40 
 jcdm-common/src/main/java/com/jcdm/common/exception/user/CaptchaExpireException.java                                      |   16 
 jcdm-admin/src/main/java/com/jcdm/web/controller/monitor/SysOperlogController.java                                        |   69 
 jcdm-generator/src/main/resources/vm/java/sub-domain.java.vm                                                              |   76 
 jcdm-main/src/main/java/com/jcdm/main/bs/formulaChild/service/IBsFormulaChildInfoService.java                             |   71 
 jcdm-generator/src/main/java/com/jcdm/generator/util/VelocityUtils.java                                                   |  408 
 jcdm-common/src/main/java/com/jcdm/common/core/text/CharsetKit.java                                                       |   86 
 jcdm-ui/src/assets/icons/svg/radio.svg                                                                                    |    1 
 jcdm-ui/src/components/Hamburger/index.vue                                                                                |   44 
 jcdm-main/src/main/java/com/jcdm/main/om/productionOrde/service/IOmProductionOrdeInfoService.java                         |   65 
 jcdm-system/src/main/resources/mapper/system/SysDictDataMapper.xml                                                        |  124 
 jcdm-ui/src/utils/index.js                                                                                                |  390 
 jcdm-framework/src/main/java/com/jcdm/framework/datasource/DynamicDataSource.java                                         |   26 
 jcdm-system/src/main/java/com/jcdm/system/service/impl/SysDeptServiceImpl.java                                            |  338 
 jcdm-main/src/main/java/com/jcdm/main/bs/formulaChild/domain/BsFormulaChildInfo.java                                      |  355 
 jcdm-ui/src/api/system/dict/data.js                                                                                       |   52 
 jcdm-ui/src/layout/components/Sidebar/SidebarItem.vue                                                                     |  100 
 jcdm-common/src/main/java/com/jcdm/common/filter/PropertyPreExcludeFilter.java                                            |   24 
 jcdm-framework/src/main/java/com/jcdm/framework/web/service/SysLoginService.java                                          |  181 
 jcdm-generator/src/main/java/com/jcdm/generator/mapper/GenTableColumnMapper.java                                          |   60 
 jcdm-ui/src/api/system/post.js                                                                                            |   44 
 jcdm-ui/src/views/tool/swagger/index.vue                                                                                  |   15 
 jcdm-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml                                                        |   34 
 jcdm-common/src/main/java/com/jcdm/common/exception/file/FileSizeLimitExceededException.java                              |   16 
 jcdm-ui/src/views/monitor/online/index.vue                                                                                |  122 
 jcdm-ui/src/views/main/bs/processes/index.vue                                                                             |  358 
 jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysIndexController.java                                           |   29 
 jcdm-ui/dist.rar                                                                                                          |    0 
 jcdm-main/src/main/resources/mapper/om/productionOrde/OmProductionOrdeInfoMapper.xml                                      |  221 
 jcdm-common/src/main/java/com/jcdm/common/annotation/Log.java                                                             |   51 
 jcdm-ui/src/components/ImageUpload/index.vue                                                                              |  226 
 jcdm-system/src/main/java/com/jcdm/system/domain/SysNotice.java                                                           |  102 
 jcdm-admin/src/main/resources/banner.txt                                                                                  |   24 
 jcdm-main/src/main/java/com/jcdm/main/bs/processFile/service/IBsProcessFileService.java                                   |   61 
 jcdm-ui/src/api/main/bs/formula/formula.js                                                                                |   44 
 jcdm-system/src/main/java/com/jcdm/system/service/ISysConfigService.java                                                  |   89 
 jcdm-main/src/main/resources/mapper/da/passingStationCollection/DaPassingStationCollectionMapper.xml                      |  144 
 jcdm-ui/src/components/Breadcrumb/index.vue                                                                               |   74 
 jcdm-system/src/main/java/com/jcdm/system/service/ISysPostService.java                                                    |   99 
 jcdm-common/src/main/java/com/jcdm/common/constant/CacheConstants.java                                                    |   44 
 jcdm-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml                                               |  153 
 jcdm-main/src/main/java/com/jcdm/main/em/equipmentAlarm/controller/EmEquipmentAlarmController.java                        |  105 
 jcdm-main/src/main/java/com/jcdm/main/bs/processes/service/impl/BsProcessesInfoServiceImpl.java                           |  100 
 jcdm-ui/src/views/monitor/operlog/index.vue                                                                               |  323 
 jcdm-main/src/main/java/com/jcdm/main/bs/productBomChild/service/impl/BsProductBomChildInfoServiceImpl.java               |   94 
 jcdm-ui/src/assets/icons/svg/code.svg                                                                                     |    1 
 jcdm-main/src/main/java/com/jcdm/main/bs/lineInfo/controller/BsLineInfoController.java                                    |  104 
 jcdm-common/src/main/java/com/jcdm/common/utils/sign/Md5Utils.java                                                        |   67 
 jcdm-ui/src/layout/components/IframeToggle/index.vue                                                                      |   33 
 jcdm-ui/public/favicon.ico                                                                                                |    0 
 jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/client/ClientHandler.java                                            |  295 
 jcdm-quartz/src/main/java/com/jcdm/quartz/domain/SysJobLog.java                                                           |  155 
 jcdm-generator/src/main/java/com/jcdm/generator/service/IGenTableService.java                                             |  121 
 jcdm-ui/src/permission.js                                                                                                 |   58 
 jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/domain/DaOpcuaConfig.java                                            |  149 
 jcdm-ui/src/plugins/cache.js                                                                                              |   77 
 jcdm-ui/src/assets/icons/svg/international.svg                                                                            |    1 
 jcdm-common/src/main/java/com/jcdm/common/utils/uuid/Seq.java                                                             |   86 
 jcdm-main/src/main/java/com/jcdm/main/em/equipmentArchives/service/IEmEquipmentArchivesService.java                       |   61 
 jcdm-ui/package.json                                                                                                      |   90 
 jcdm-ui/src/assets/icons/svg/guide.svg                                                                                    |    1 
 jcdm-ui/src/assets/icons/svg/slider.svg                                                                                   |    1 
 jcdm-ui/src/api/system/config.js                                                                                          |   60 
 jcdm-ui/src/utils/generator/js.js                                                                                         |  235 
 jcdm-ui/build/index.js                                                                                                    |   35 
 jcdm-quartz/src/main/java/com/jcdm/quartz/mapper/SysJobMapper.java                                                        |   67 
 jcdm-ui/src/assets/icons/svg/star.svg                                                                                     |    1 
 jcdm-main/src/main/resources/mapper/bs/formula/BsFormulaInfoMapper.xml                                                    |  109 
 jcdm-ui/src/views/dashboard/PieChart.vue                                                                                  |   79 
 jcdm-system/src/main/java/com/jcdm/system/mapper/SysOperLogMapper.java                                                    |   48 
 jcdm-ui/src/assets/icons/svg/checkbox.svg                                                                                 |    1 
 jcdm-ui/src/components/ThemePicker/index.vue                                                                              |  173 
 jcdm-ui/src/views/system/user/profile/userAvatar.vue                                                                      |  184 
 jcdm-framework/src/main/java/com/jcdm/framework/config/RedisConfig.java                                                   |   69 
 jcdm-common/src/main/java/com/jcdm/common/utils/ServletUtils.java                                                         |  218 
 jcdm-ui/src/assets/icons/svg/logininfor.svg                                                                               |    1 
 jcdm-ui/src/assets/icons/svg/404.svg                                                                                      |    1 
 jcdm-main/src/main/java/com/jcdm/main/om/productionOrde/controller/OmProductionOrdeInfoController.java                    |  114 
 jcdm-system/src/main/java/com/jcdm/system/service/impl/SysOperLogServiceImpl.java                                         |   76 
 jcdm-framework/src/main/java/com/jcdm/framework/config/SecurityConfig.java                                                |  148 
 jcdm-ui/src/api/monitor/jobLog.js                                                                                         |   26 
 jcdm-ui/src/views/redirect.vue                                                                                            |   12 
 jcdm-ui/src/views/main/da/paramCollection/index.vue                                                                       |  374 
 jcdm-ui/src/views/tool/build/CodeTypeDialog.vue                                                                           |  106 
 jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysUser.java                                                 |  324 
 jcdm-main/src/main/java/com/jcdm/main/em/equipmentAlarm/service/IEmEquipmentAlarmService.java                             |   62 
 jcdm-main/src/main/resources/mapper/bs/lineInfo/BsLineInfoMapper.xml                                                      |  107 
 jcdm-common/src/main/java/com/jcdm/common/utils/ip/IpUtils.java                                                           |  382 
 jcdm-ui/src/components/Crontab/min.vue                                                                                    |  116 
 .gitignore                                                                                                                |   47 
 jcdm-system/src/main/java/com/jcdm/system/domain/SysConfig.java                                                           |  111 
 jcdm-main/src/main/java/com/jcdm/main/sc/stationConf/mapper/ScStationConfMapper.java                                      |   61 
 jcdm-system/src/main/resources/mapper/system/SysUserMapper.xml                                                            |  223 
 jcdm-ui/src/api/system/dept.js                                                                                            |   52 
 jcdm-ui/src/api/tool/gen.js                                                                                               |   76 
 jcdm-common/src/main/java/com/jcdm/common/exception/base/BaseException.java                                               |   97 
 jcdm-ui/src/views/main/cfkb/Instructions/index.vue                                                                        |  270 
 jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysLoginController.java                                           |   86 
 jcdm-main/src/main/java/com/jcdm/main/da/collectionParamConf/service/IDaCollectionParamConfService.java                   |   62 
 jcdm-system/src/main/java/com/jcdm/system/domain/vo/RouterVo.java                                                         |  148 
 jcdm-ui/src/components/Crontab/hour.vue                                                                                   |  114 
 jcdm-system/src/main/java/com/jcdm/system/domain/SysPost.java                                                             |  124 
 jcdm-ui/src/assets/icons/svg/link.svg                                                                                     |    1 
 jcdm-ui/src/views/tool/build/index.vue                                                                                    |  768 
 jcdm-main/src/main/java/com/jcdm/main/em/equipmentAlarm/service/impl/EmEquipmentAlarmServiceImpl.java                     |   94 
 jcdm-ui/src/views/main/kb/stationTerminal/index.vue                                                                       |  445 
 jcdm-ui/src/api/login.js                                                                                                  |   60 
 jcdm-common/src/main/java/com/jcdm/common/utils/sql/SqlUtil.java                                                          |   70 
 jcdm-ui/src/assets/icons/svg/date-range.svg                                                                               |    1 
 jcdm-main/src/main/java/com/jcdm/main/bs/workshop/mapper/BsWorkshopInfoMapper.java                                        |   61 
 jcdm-common/src/main/java/com/jcdm/common/utils/file/FileUtils.java                                                       |  291 
 jcdm-main/src/main/java/com/jcdm/main/bs/processFile/service/impl/BsProcessFileServiceImpl.java                           |   96 
 jcdm-main/src/main/resources/mapper/em/equipmentArchives/EmEquipmentArchivesMapper.xml                                    |  155 
 jcdm-ui/src/views/main/bs/material/index.vue                                                                              |  413 
 jcdm-ui/src/views/system/role/index.vue                                                                                   |  605 
 jcdm-generator/src/main/java/com/jcdm/generator/util/VelocityInitializer.java                                             |   34 
 jcdm-framework/src/main/java/com/jcdm/framework/config/FastJson2JsonRedisSerializer.java                                  |   52 
 jcdm-ui/src/assets/icons/svg/password.svg                                                                                 |    1 
 jcdm-ui/src/api/main/rm/repairData/repairData.js                                                                          |   44 
 jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/controller/DaPassingStationCollectionController.java    |  133 
 jcdm-ui/src/assets/icons/index.js                                                                                         |    9 
 jcdm-ui/src/assets/icons/svg/peoples.svg                                                                                  |    1 
 jcdm-main/src/main/java/com/jcdm/main/bs/technologyRouteChild/service/IBsTechnologyRouteChildInfoService.java             |   61 
 jcdm-ui/src/api/monitor/server.js                                                                                         |    9 
 jcdm-common/src/main/java/com/jcdm/common/utils/reflect/ReflectUtils.java                                                 |  410 
 jcdm-generator/src/main/resources/mapper/generator/GenTableMapper.xml                                                     |  227 
 jcdm-admin/src/main/java/com/jcdm/web/core/config/SwaggerConfig.java                                                      |  125 
 jcdm-common/src/main/java/com/jcdm/common/filter/XssFilter.java                                                           |   75 
 jcdm-ui/src/directive/permission/hasPermi.js                                                                              |   28 
 jcdm-framework/src/main/java/com/jcdm/framework/config/KaptchaTextCreator.java                                            |   68 
 jcdm-ui/src/assets/icons/svg/bug.svg                                                                                      |    1 
 jcdm-ui/src/components/Crontab/second.vue                                                                                 |  117 
 jcdm-common/src/main/java/com/jcdm/common/utils/sign/Base64.java                                                          |  291 
 jcdm-system/src/main/java/com/jcdm/system/service/impl/SysLogininforServiceImpl.java                                      |   65 
 jcdm-system/src/main/java/com/jcdm/system/domain/SysUserRole.java                                                         |   46 
 jcdm-ui/src/api/system/menu.js                                                                                            |   60 
 jcdm-ui/src/assets/icons/svg/date.svg                                                                                     |    1 
 jcdm-ui/src/components/Crontab/day.vue                                                                                    |  161 
 jcdm-system/src/main/resources/mapper/system/SysLogininforMapper.xml                                                      |   59 
 jcdm-framework/src/main/java/com/jcdm/framework/config/properties/DruidProperties.java                                    |   89 
 jcdm-main/src/main/java/com/jcdm/main/bs/workshop/service/IBsWorkshopInfoService.java                                     |   61 
 jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/controller/DaOpcuaConfigController.java                              |   98 
 jcdm-ui/src/assets/404_images/404.png                                                                                     |    0 
 jcdm-ui/src/utils/generator/html.js                                                                                       |  359 
 jcdm-ui/src/api/system/notice.js                                                                                          |   44 
 jcdm-ui/src/assets/icons/svg/icon.svg                                                                                     |    1 
 jcdm-ui/src/api/monitor/job.js                                                                                            |   71 
 jcdm-ui/src/assets/icons/svg/question.svg                                                                                 |    1 
 jcdm-ui/src/store/modules/permission.js                                                                                   |  137 
 jcdm-ui/src/views/index_v1.vue                                                                                            |   98 
 jcdm-ui/src/assets/icons/svg/tool.svg                                                                                     |    1 
 jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/service/impl/DaPassingStationCollectionServiceImpl.java |  147 
 jcdm-ui/src/utils/dict/Dict.js                                                                                            |   82 
 jcdm-framework/src/main/java/com/jcdm/framework/aspectj/DataSourceAspect.java                                             |   72 
 jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/common/Constants.java                                   |    5 
 jcdm-common/src/main/java/com/jcdm/common/constant/GenConstants.java                                                      |  117 
 jcdm-system/src/main/java/com/jcdm/system/service/impl/SysUserOnlineServiceImpl.java                                      |   96 
 jcdm-admin/pom.xml                                                                                                        |  108 
 jcdm-ui/src/views/tool/gen/importTable.vue                                                                                |  120 
 jcdm-ui/src/components/IconSelect/index.vue                                                                               |  104 
 jcdm-main/src/main/java/com/jcdm/main/bs/workshop/domain/BsWorkshopInfo.java                                              |  144 
 jcdm-ui/.env.staging                                                                                                      |   10 
 jcdm-main/src/main/java/com/jcdm/main/bs/productBomChild/controller/BsProductBomChildInfoController.java                  |  110 
 jcdm-main/src/main/resources/mapper/da/paramCollection/DaParamCollectionMapper.xml                                        |  149 
 jcdm-ui/src/assets/icons/svg/tree-table.svg                                                                               |    1 
 jcdm-main/src/main/resources/mapper/bs/productBom/BsProductBomInfoMapper.xml                                              |  114 
 jcdm-ui/src/assets/icons/svg/shopping.svg                                                                                 |    1 
 jcdm-framework/src/main/java/com/jcdm/framework/websocket/WebSocketConfig.java                                            |   20 
 jcdm-main/src/main/java/com/jcdm/main/em/equipmentStatus/controller/EmEquipmentStatusController.java                      |  104 
 jcdm-ui/src/layout/components/Sidebar/Item.vue                                                                            |   33 
 jcdm-ui/src/components/Crontab/year.vue                                                                                   |  131 
 jcdm-ui/src/api/main/em/equipmentArchives/equipmentArchives.js                                                            |   44 
 jcdm-ui/src/assets/icons/svg/theme.svg                                                                                    |    1 
 jcdm-main/src/main/java/com/jcdm/main/bs/technologyRouteChild/mapper/BsTechnologyRouteChildInfoMapper.java                |   64 
 jcdm-common/src/main/java/com/jcdm/common/core/domain/model/LoginUser.java                                                |  266 
 jcdm-main/src/main/resources/mapper/rm/repairRecord/RmRepairRecordMapper.xml                                              |  119 
 jcdm-common/src/main/java/com/jcdm/common/core/domain/model/LoginBody.java                                                |   69 
 jcdm-ui/src/assets/icons/svg/select.svg                                                                                   |    1 
 jcdm-ui/src/assets/icons/svg/fullscreen.svg                                                                               |    1 
 jcdm-framework/src/main/java/com/jcdm/framework/web/domain/server/Sys.java                                                |   84 
 jcdm-main/src/main/resources/mapper/bs/workshop/BsWorkshopInfoMapper.xml                                                  |   97 
 jcdm-ui/src/views/main/rm/repairData/index.vue                                                                            |  398 
 jcdm-ui/src/views/tool/gen/index.vue                                                                                      |  337 
 jcdm-common/src/main/java/com/jcdm/common/config/MesConfig.java                                                           |  135 
 jcdm-ui/src/views/system/menu/index.vue                                                                                   |  452 
 jcdm-admin/src/main/java/com/jcdm/web/controller/monitor/SysUserOnlineController.java                                     |   83 
 jcdm-system/src/main/java/com/jcdm/system/mapper/SysUserMapper.java                                                       |  127 
 jcdm-ui/src/components/RuoYi/Git/index.vue                                                                                |   21 
 jcdm-ui/src/views/main/em/equipmentAlarm/index.vue                                                                        |  377 
 jcdm-quartz/src/main/java/com/jcdm/quartz/util/AbstractQuartzJob.java                                                     |  107 
 jcdm-main/src/main/java/com/jcdm/main/rm/repairData/domain/RmRepairData.java                                              |  233 
 jcdm-common/src/main/java/com/jcdm/common/exception/file/InvalidExtensionException.java                                   |   80 
 jcdm-framework/src/main/java/com/jcdm/framework/security/context/AuthenticationContextHolder.java                         |   28 
 jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysDictDataController.java                                        |  121 
 jcdm-framework/src/main/java/com/jcdm/framework/security/context/PermissionContextHolder.java                             |   27 
 jcdm-framework/src/main/java/com/jcdm/framework/config/ThreadPoolConfig.java                                              |   63 
 jcdm-generator/src/main/java/com/jcdm/generator/config/GenConfig.java                                                     |   73 
 jcdm-generator/src/main/resources/vm/vue/index-tree.vue.vm                                                                |  505 
 jcdm-ui/src/api/main/bs/workshop/workshop.js                                                                              |   44 
 jcdm-common/src/main/java/com/jcdm/common/constant/HttpStatus.java                                                        |   94 
 jcdm-ui/src/assets/styles/element-variables.scss                                                                          |   31 
 jcdm-generator/src/main/java/com/jcdm/generator/util/GenUtils.java                                                        |  257 
 jcdm-main/src/main/java/com/jcdm/main/om/productionOrde/service/impl/OmProductionOrdeInfoServiceImpl.java                 |  137 
 jcdm-generator/src/main/resources/generator.yml                                                                           |   10 
 jcdm-system/src/main/java/com/jcdm/system/service/impl/SysConfigServiceImpl.java                                          |  232 
 jcdm-ui/src/assets/401_images/401.gif                                                                                     |    0 
 jcdm-ui/src/assets/styles/variables.scss                                                                                  |   54 
 jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/cert/MethodName.java                                                 |  169 
 jcdm-ui/src/layout/components/Sidebar/FixiOSBug.js                                                                        |   25 
 jcdm-admin/src/main/resources/logback.xml                                                                                 |   93 
 jcdm-framework/src/main/java/com/jcdm/framework/config/CaptchaConfig.java                                                 |   83 
 jcdm-ui/src/views/tool/build/TreeNodeDialog.vue                                                                           |  149 
 jcdm-common/src/main/java/com/jcdm/common/utils/http/HttpHelper.java                                                      |   55 
 jcdm-main/src/main/java/com/jcdm/main/om/workReport/controller/OmWorkReportController.java                                |  104 
 jcdm-main/src/main/java/com/jcdm/main/bs/formulaChild/controller/BsFormulaChildInfoController.java                        |  137 
 jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysRegisterController.java                                        |   38 
 jcdm-common/src/main/java/com/jcdm/common/utils/poi/ExcelUtil.java                                                        | 1758 +
 jcdm-main/src/main/java/com/jcdm/main/bs/beatSetting/controller/BsBeatSettingController.java                              |  104 
 jcdm-common/src/main/java/com/jcdm/common/utils/DateUtils.java                                                            |  191 
 jcdm-system/src/main/java/com/jcdm/system/service/ISysOperLogService.java                                                 |   48 
 jcdm-common/src/main/java/com/jcdm/common/exception/user/UserPasswordNotMatchException.java                               |   16 
 jcdm-common/src/main/java/com/jcdm/common/utils/PageUtils.java                                                            |   35 
 jcdm-ui/src/utils/request.js                                                                                              |  152 
 jcdm-admin/src/main/java/com/jcdm/web/controller/common/CaptchaController.java                                            |   94 
 jcdm-quartz/src/main/java/com/jcdm/quartz/task/RyTask.java                                                                |   28 
 jcdm-ui/src/assets/icons/svg/build.svg                                                                                    |    1 
 jcdm-ui/src/views/tool/build/DraggableItem.vue                                                                            |  100 
 jcdm-main/src/main/java/com/jcdm/main/bs/material/mapper/BsMaterialInfoMapper.java                                        |   62 
 jcdm-system/src/main/java/com/jcdm/system/service/impl/SysDictTypeServiceImpl.java                                        |  223 
 jcdm-ui/.env.production                                                                                                   |    8 
 jcdm-ui/src/views/system/user/profile/resetPwd.vue                                                                        |   68 
 jcdm-common/src/main/java/com/jcdm/common/filter/RepeatedlyRequestWrapper.java                                            |   76 
 jcdm-common/src/main/java/com/jcdm/common/exception/file/FileUploadException.java                                         |   61 
 jcdm-framework/src/main/java/com/jcdm/framework/web/domain/server/Mem.java                                                |   61 
 jcdm-ui/src/api/monitor/cache.js                                                                                          |   57 
 jcdm-ui/src/views/monitor/druid/index.vue                                                                                 |   15 
 jcdm-quartz/src/main/java/com/jcdm/quartz/service/ISysJobService.java                                                     |  102 
 jcdm-ui/src/components/Pagination/index.vue                                                                               |  114 
 jcdm-system/src/main/resources/mapper/system/SysDeptMapper.xml                                                            |  160 
 jcdm-quartz/src/main/java/com/jcdm/quartz/util/JobInvokeUtil.java                                                         |  182 
 jcdm-common/src/main/java/com/jcdm/common/core/redis/MyCache.java                                                         |   86 
 jcdm-framework/src/main/java/com/jcdm/framework/manager/AsyncManager.java                                                 |   55 
 jcdm-admin/src/main/resources/mybatis/mybatis-config.xml                                                                  |   20 
 jcdm-ui/src/assets/icons/svg/skill.svg                                                                                    |    1 
 jcdm-common/src/main/java/com/jcdm/common/exception/user/UserException.java                                               |   18 
 jcdm-quartz/src/main/java/com/jcdm/quartz/controller/SysJobController.java                                                |  185 
 jcdm-ui/src/assets/icons/svg/size.svg                                                                                     |    1 
 jcdm-ui/src/assets/icons/svg/download.svg                                                                                 |    1 
 jcdm-ui/src/components/PanThumb/index.vue                                                                                 |  142 
 package-lock.json                                                                                                         |    6 
 jcdm-main/src/main/java/com/jcdm/main/webservice/ItemList.java                                                            |   22 
 jcdm-main/src/main/java/com/jcdm/main/rm/repairData/service/IRmRepairDataService.java                                     |   61 
 pom.xml                                                                                                                   |  240 
 jcdm-ui/src/App.vue                                                                                                       |   28 
 jcdm-main/src/main/java/com/jcdm/main/util/IpInfoUtils.java                                                               |   63 
 jcdm-ui/src/assets/icons/svg/chart.svg                                                                                    |    1 
 jcdm-ui/src/components/DictData/index.js                                                                                  |   49 
 jcdm-ui/src/api/system/user.js                                                                                            |  135 
 jcdm-ui/vue.config.js                                                                                                     |  132 
 jcdm-system/src/main/java/com/jcdm/system/domain/SysRoleMenu.java                                                         |   46 
 jcdm-main/src/main/java/com/jcdm/main/bs/formula/mapper/BsFormulaInfoMapper.java                                          |   61 
 jcdm-ui/src/components/SvgIcon/index.vue                                                                                  |   61 
 jcdm-quartz/src/main/resources/mapper/quartz/SysJobLogMapper.xml                                                          |   93 
 jcdm-ui/src/assets/styles/sidebar.scss                                                                                    |  227 
 sql/quartz.sql                                                                                                            |  174 
 jcdm-framework/src/main/java/com/jcdm/framework/websocket/SemaphoreUtils.java                                             |   58 
 jcdm-main/src/main/java/com/jcdm/main/rm/repairRecord/controller/RmRepairRecordController.java                            |  104 
 jcdm-system/src/main/java/com/jcdm/system/mapper/SysPostMapper.java                                                       |   99 
 jcdm-ui/src/layout/components/Sidebar/index.vue                                                                           |   57 
 jcdm-main/src/main/java/com/jcdm/main/bs/technologyRoute/mapper/BsTechnologyRouteInfoMapper.java                          |   62 
 jcdm-main/src/main/java/com/jcdm/main/bs/formula/controller/BsFormulaInfoController.java                                  |  104 
 jcdm-system/src/main/java/com/jcdm/system/service/ISysLogininforService.java                                              |   40 
 jcdm-system/src/main/java/com/jcdm/system/domain/SysUserOnline.java                                                       |  113 
 jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/domain/NodeEntity.java                                               |   19 
 jcdm-quartz/src/main/java/com/jcdm/quartz/controller/SysJobLogController.java                                             |   92 
 jcdm-framework/src/main/java/com/jcdm/framework/websocket/WebSocketUsers.java                                             |  140 
 jcdm-ui/src/assets/icons/svg/table.svg                                                                                    |    1 
 jcdm-ui/src/utils/generator/config.js                                                                                     |  438 
 jcdm-common/src/main/java/com/jcdm/common/enums/DataSourceType.java                                                       |   19 
 jcdm-ui/src/assets/styles/transition.scss                                                                                 |   49 
 jcdm-common/src/main/java/com/jcdm/common/utils/uuid/IdUtils.java                                                         |   49 
 jcdm-ui/src/assets/icons/svg/system.svg                                                                                   |    2 
 jcdm-common/src/main/java/com/jcdm/common/core/domain/TreeEntity.java                                                     |   79 
 jcdm-ui/src/assets/icons/svg/wechat.svg                                                                                   |    1 
 jcdm-ui/src/assets/icons/svg/component.svg                                                                                |    1 
 LICENSE                                                                                                                   |   20 
 jcdm-main/src/main/java/com/jcdm/main/bs/processFile/controller/BsProcessFileController.java                              |  104 
 jcdm-ui/src/components/SizeSelect/index.vue                                                                               |   56 
 jcdm-ui/src/assets/icons/svg/monitor.svg                                                                                  |    2 
 jcdm-ui/src/views/tool/gen/basicInfoForm.vue                                                                              |   60 
 jcdm-framework/pom.xml                                                                                                    |   70 
 jcdm-main/src/main/java/com/jcdm/main/rm/repairRecord/domain/RmRepairRecord.java                                          |  207 
 jcdm-ui/src/router/index.js                                                                                               |  239 
 jcdm-ui/src/store/modules/dict.js                                                                                         |   50 
 jcdm-main/src/main/java/com/jcdm/main/da/paramCollection/service/impl/DaParamCollectionServiceImpl.java                   |   97 
 jcdm-ui/.eslintrc.js                                                                                                      |  199 
 jcdm-ui/src/api/main/sc/stationConf.js                                                                                    |   52 
 jcdm-ui/src/api/main/bs/technologyRouteChild/technologyRouteChild.js                                                      |   44 
 jcdm-main/src/main/resources/mapper/bs/productBomChild/BsProductBomChildInfoMapper.xml                                    |  107 
 jcdm-ui/src/views/system/role/selectUser.vue                                                                              |  138 
 jcdm-framework/src/main/java/com/jcdm/framework/websocket/WebSocketServer.java                                            |  108 
 jcdm-main/src/main/java/com/jcdm/main/bs/technologyRoute/service/IBsTechnologyRouteInfoService.java                       |   64 
 jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/init/OpcusConfigInit.java                                            |   48 
 jcdm-admin/src/main/resources/i18n/messages.properties                                                                    |   38 
 jcdm-main/src/main/resources/mapper/bs/material/BsMaterialInfoMapper.xml                                                  |  136 
 jcdm-ui/src/views/monitor/cache/list.vue                                                                                  |  241 
 jcdm-generator/src/main/resources/vm/java/service.java.vm                                                                 |   61 
 jcdm-main/src/main/java/com/jcdm/main/da/paramCollection/mapper/DaParamCollectionMapper.java                              |   62 
 jcdm-ui/src/views/system/user/profile/userInfo.vue                                                                        |   88 
 jcdm-ui/src/assets/styles/btn.scss                                                                                        |   99 
 jcdm-main/src/main/java/com/jcdm/main/bs/processes/mapper/BsProcessesInfoMapper.java                                      |   62 
 jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysDictType.java                                             |   96 
 jcdm-ui/src/api/main/da/collectionParamConf/collectionParamConf.js                                                        |   44 
 jcdm-ui/src/assets/icons/svg/redis.svg                                                                                    |    1 
 jcdm-ui/src/assets/icons/svg/online.svg                                                                                   |    1 
 jcdm-ui/src/assets/icons/svg/github.svg                                                                                   |    1 
 jcdm-ui/src/api/main/bs/processes/processes.js                                                                            |   44 
 jcdm-common/src/main/java/com/jcdm/common/exception/UtilException.java                                                    |   26 
 jcdm-ui/src/assets/images/pay.png                                                                                         |    0 
 jcdm-ui/src/store/modules/user.js                                                                                         |  101 
 jcdm-main/src/main/java/com/jcdm/main/rm/repairData/controller/RmRepairDataController.java                                |  104 
 jcdm-common/src/main/java/com/jcdm/common/utils/StringUtils.java                                                          |  638 
 jcdm-main/src/main/java/com/jcdm/main/da/collectionParamConf/mapper/DaCollectionParamConfMapper.java                      |   62 
 jcdm-ui/src/utils/dict/DictConverter.js                                                                                   |   17 
 jcdm-ui/src/components/ImagePreview/index.vue                                                                             |   90 
 jcdm-ui/src/views/main/bs/ProductBomChild/index.vue                                                                       |  457 
 jcdm-main/src/main/java/com/jcdm/main/da/collectionParamConf/service/impl/DaCollectionParamConfServiceImpl.java           |   97 
 jcdm-admin/src/main/resources/META-INF/spring-devtools.properties                                                         |    1 
 jcdm-main/src/main/java/com/jcdm/main/bs/material/service/IBsMaterialInfoService.java                                     |   62 
 jcdm-ui/src/api/main/em/equipmentStatus/equipmentStatus.js                                                                |   44 
 jcdm-ui/src/views/monitor/logininfor/index.vue                                                                            |  246 
 jcdm-ui/src/assets/icons/svg/job.svg                                                                                      |    1 
 jcdm-ui/src/components/itemSelect/index.vue                                                                               |  223 
 jcdm-system/src/main/java/com/jcdm/system/service/ISysUserOnlineService.java                                              |   48 
 jcdm-ui/src/api/main/bs/ProductBom/ProductBom.js                                                                          |   44 
 jcdm-framework/src/main/java/com/jcdm/framework/web/service/TokenService.java                                             |  231 
 jcdm-ui/src/assets/icons/svg/phone.svg                                                                                    |    1 
 jcdm-ui/src/components/TopNav/index.vue                                                                                   |  195 
 jcdm-ui/src/utils/dict/DictMeta.js                                                                                        |   38 
 jcdm-system/src/main/java/com/jcdm/system/mapper/SysDictDataMapper.java                                                   |   95 
 jcdm-ui/src/assets/icons/svg/lock.svg                                                                                     |    1 
 jcdm-common/src/main/java/com/jcdm/common/utils/Arith.java                                                                |  114 
 jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysRoleController.java                                            |  262 
 jcdm-common/src/main/java/com/jcdm/common/exception/ServiceException.java                                                 |   74 
 jcdm-ui/src/views/main/bs/formulaChild/index.vue                                                                          |  474 
 jcdm-ui/src/layout/components/AppMain.vue                                                                                 |   75 
 jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysRole.java                                                 |  241 
 jcdm-main/src/main/java/com/jcdm/main/om/workReport/domain/OmWorkReport.java                                              |  223 
 jcdm-main/src/main/java/com/jcdm/main/bs/workshop/service/impl/BsWorkshopInfoServiceImpl.java                             |  100 
 jcdm-system/src/main/java/com/jcdm/system/domain/SysLogininfor.java                                                       |  144 
 jcdm-common/src/main/java/com/jcdm/common/exception/user/UserNotExistsException.java                                      |   16 
 jcdm-admin/src/main/resources/application.yml                                                                             |  132 
 jcdm-admin/src/main/java/com/jcdm/MesServletInitializer.java                                                              |   18 
 jcdm-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm                                                             |  474 
 jcdm-main/src/main/java/com/jcdm/main/em/equipmentArchives/controller/EmEquipmentArchivesController.java                  |  104 
 jcdm-quartz/src/main/java/com/jcdm/quartz/util/ScheduleUtils.java                                                         |  141 
 jcdm-main/src/main/java/com/jcdm/main/bs/technologyRoute/service/impl/BsTechnologyRouteInfoServiceImpl.java               |  119 
 jcdm-main/src/main/java/com/jcdm/main/bs/processes/controller/BsProcessesInfoController.java                              |  105 
 jcdm-main/src/main/resources/mapper/bs/processFile/BsProcessFileMapper.xml                                                |  130 
 jcdm-main/src/main/java/com/jcdm/main/bs/beatSetting/domain/BsBeatSetting.java                                            |  152 
 jcdm-generator/src/main/resources/vm/java/domain.java.vm                                                                  |  105 
 jcdm-ui/src/plugins/auth.js                                                                                               |   60 
 jcdm-quartz/src/main/java/com/jcdm/quartz/service/impl/SysJobServiceImpl.java                                             |  261 
 jcdm-ui/src/api/monitor/online.js                                                                                         |   18 
 jcdm-common/src/main/java/com/jcdm/common/core/page/TableSupport.java                                                     |   56 
 jcdm-ui/src/assets/icons/svg/post.svg                                                                                     |    1 
 jcdm-main/src/main/java/com/jcdm/main/bs/processFile/domain/BsProcessFile.java                                            |  245 
 jcdm-common/src/main/java/com/jcdm/common/utils/http/HttpUtils.java                                                       |  274 
 jcdm-main/src/main/java/com/jcdm/main/bs/beatSetting/mapper/BsBeatSettingMapper.java                                      |   61 
 jcdm-ui/src/utils/dict/index.js                                                                                           |   33 
 jcdm-ui/src/assets/logo/logo.png                                                                                          |    0 
 jcdm-common/src/main/java/com/jcdm/common/utils/Threads.java                                                              |   99 
 jcdm-system/src/main/java/com/jcdm/system/service/ISysDictDataService.java                                                |   60 
 jcdm-common/src/main/java/com/jcdm/common/constant/ScheduleConstants.java                                                 |   50 
 jcdm-common/src/main/java/com/jcdm/common/constant/UserConstants.java                                                     |   78 
 jcdm-ui/src/api/main/bs/ProductBomChild/ProductBomChild.js                                                                |   44 
 jcdm-generator/src/main/java/com/jcdm/generator/controller/GenController.java                                             |  214 
 jcdm-common/src/main/java/com/jcdm/common/utils/ip/AddressUtils.java                                                      |   56 
 jcdm-common/src/main/java/com/jcdm/common/core/domain/TreeSelect.java                                                     |   77 
 jcdm-common/src/main/java/com/jcdm/common/exception/user/UserPasswordRetryLimitExceedException.java                       |   16 
 jcdm-main/src/main/java/com/jcdm/main/sc/stationConf/service/impl/ScStationConfServiceImpl.java                           |  109 
 jcdm-ui/src/directive/dialog/dragHeight.js                                                                                |   34 
 jcdm-framework/src/main/java/com/jcdm/framework/web/service/PermissionService.java                                        |  159 
 jcdm-system/src/main/java/com/jcdm/system/domain/SysUserPost.java                                                         |   46 
 jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/init/BeanUtils.java                                                  |   30 
 jcdm-ui/src/api/main/bs/material/material.js                                                                              |   44 
 jcdm-main/src/main/java/com/jcdm/main/bs/beatSetting/service/impl/BsBeatSettingServiceImpl.java                           |   96 
 jcdm-main/src/main/java/com/jcdm/main/bs/technologyRoute/controller/BsTechnologyRouteInfoController.java                  |  116 
 jcdm-ui/.gitignore                                                                                                        |   23 
 jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysPostController.java                                            |  129 
 jcdm-ui/src/utils/generator/drawingDefault.js                                                                             |   29 
 jcdm-ui/src/layout/components/Sidebar/Logo.vue                                                                            |   93 
 jcdm-system/src/main/java/com/jcdm/system/mapper/SysMenuMapper.java                                                       |  125 
 jcdm-ui/src/assets/icons/svg/drag.svg                                                                                     |    1 
 jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/client/ClientRunner.java                                             |  146 
 jcdm-common/src/main/java/com/jcdm/common/constant/Constants.java                                                         |  167 
 jcdm-ui/src/views/system/post/index.vue                                                                                   |  309 
 jcdm-main/src/main/resources/mapper/em/equipmentStatus/EmEquipmentStatusMapper.xml                                        |   99 
 jcdm-quartz/src/main/java/com/jcdm/quartz/service/impl/SysJobLogServiceImpl.java                                          |   87 
 doc/╚⌠╥└╗╖╛│╩╣╙├╩╓▓ß.docx                                                                                                 |    0 
 jcdm-common/src/main/java/com/jcdm/common/annotation/RateLimiter.java                                                     |   40 
 jcdm-common/src/main/java/com/jcdm/common/filter/RepeatableFilter.java                                                    |   52 
 jcdm-system/src/main/resources/mapper/system/SysPostMapper.xml                                                            |  124 
 jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysDictData.java                                             |  176 
 jcdm-main/src/main/java/com/jcdm/main/em/equipmentAlarm/mapper/EmEquipmentAlarmMapper.java                                |   62 
 jcdm-framework/src/main/java/com/jcdm/framework/web/domain/server/SysFile.java                                            |  114 
 jcdm-common/src/main/java/com/jcdm/common/utils/file/ImageUtils.java                                                      |   98 
 jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysDictTypeController.java                                        |  131 
 jcdm-ui/src/layout/components/InnerLink/index.vue                                                                         |   47 
 jcdm-framework/src/main/java/com/jcdm/framework/config/MyBatisConfig.java                                                 |  132 
 jcdm-system/src/main/java/com/jcdm/system/service/ISysDictTypeService.java                                                |   98 
 jcdm-ui/bin/run-web.bat                                                                                                   |   12 
 jcdm-ui/src/views/register.vue                                                                                            |  209 
 jcdm-ui/src/components/iFrame/index.vue                                                                                   |   36 
 jcdm-main/src/main/java/com/jcdm/main/om/workReport/service/IOmWorkReportService.java                                     |   61 
 jcdm-ui/src/components/HeaderSearch/index.vue                                                                             |  198 
 jcdm-quartz/src/main/java/com/jcdm/quartz/mapper/SysJobLogMapper.java                                                     |   64 
 jcdm-ui/src/assets/icons/svg/druid.svg                                                                                    |    1 
 jcdm-ui/src/directive/permission/hasRole.js                                                                               |   28 
 jcdm-ui/src/assets/icons/svg/validCode.svg                                                                                |    1 
 jcdm-ui/src/views/main/bs/technologyRouteChild/index.vue                                                                  |  459 
 jcdm-framework/src/main/java/com/jcdm/framework/interceptor/RepeatSubmitInterceptor.java                                  |   56 
 jcdm-main/src/main/java/com/jcdm/main/bs/material/domain/BsMaterialInfo.java                                              |  249 
 jcdm-system/src/main/resources/mapper/system/SysRoleMapper.xml                                                            |  166 
 jcdm-ui/src/components/FileUpload/index.vue                                                                               |  216 
 jcdm-main/src/main/java/com/jcdm/main/bs/formula/service/impl/BsFormulaInfoServiceImpl.java                               |   96 
 jcdm-system/src/main/java/com/jcdm/system/domain/SysOperLog.java                                                          |  269 
 jcdm-common/src/main/java/com/jcdm/common/xss/Xss.java                                                                    |   27 
 jcdm-common/src/main/java/com/jcdm/common/core/redis/RedisCache.java                                                      |  279 
 jcdm-common/src/main/java/com/jcdm/common/core/domain/model/RegisterBody.java                                             |   11 
 jcdm-ui/src/layout/components/index.js                                                                                    |    5 
 jcdm-framework/src/main/java/com/jcdm/framework/web/service/SysPermissionService.java                                     |   83 
 jcdm-ui/src/layout/components/Settings/index.vue                                                                          |  260 
 jcdm-common/src/main/java/com/jcdm/common/utils/MessageUtils.java                                                         |   26 
 jcdm-ui/src/assets/icons/svg/cascader.svg                                                                                 |    1 
 jcdm-ui/src/assets/icons/svg/dict.svg                                                                                     |    1 
 jcdm-common/src/main/java/com/jcdm/common/annotation/Excel.java                                                           |  187 
 jcdm-main/src/main/java/com/jcdm/main/rm/repairRecord/mapper/RmRepairRecordMapper.java                                    |   61 
 jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysUserController.java                                            |  251 
 jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysConfigController.java                                          |  133 
 jcdm-framework/src/main/java/com/jcdm/framework/aspectj/LogAspect.java                                                    |  249 
 jcdm-ui/src/utils/permission.js                                                                                           |   47 
 jcdm-ui/src/views/main/da/collectionParamConf/index.vue                                                                   |  443 
 jcdm-ui/bin/build.bat                                                                                                     |   12 
 jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysDeptController.java                                            |  132 
 jcdm-ui/src/assets/icons/svg/input.svg                                                                                    |    1 
 jcdm-ui/src/assets/icons/svg/row.svg                                                                                      |    1 
 jcdm-generator/src/main/resources/vm/vue/v3/index.vue.vm                                                                  |  590 
 jcdm-system/src/main/java/com/jcdm/system/domain/SysCache.java                                                            |   81 
 bin/clean.bat                                                                                                             |   12 
 jcdm-framework/src/main/java/com/jcdm/framework/web/service/SysPasswordService.java                                       |   94 
 jcdm-ui/src/views/system/config/index.vue                                                                                 |  343 
 jcdm-common/src/main/java/com/jcdm/common/enums/LimitType.java                                                            |   20 
 jcdm-ui/src/assets/icons/svg/time-range.svg                                                                               |    1 
 jcdm-ui/public/index.html                                                                                                 |  208 
 jcdm-ui/src/views/monitor/job/log.vue                                                                                     |  295 
 jcdm-generator/src/main/java/com/jcdm/generator/service/GenTableColumnServiceImpl.java                                    |   68 
 jcdm-ui/src/views/system/notice/index.vue                                                                                 |  312 
 jcdm-common/src/main/java/com/jcdm/common/exception/file/FileNameLengthLimitExceededException.java                        |   16 
 jcdm-main/src/main/java/com/jcdm/main/rm/repairData/service/impl/RmRepairDataServiceImpl.java                             |   96 
 jcdm-ui/src/components/Crontab/week.vue                                                                                   |  202 
 jcdm-ui/src/views/main/bs/processFile/index.vue                                                                           |  506 
 jcdm-quartz/src/main/java/com/jcdm/quartz/service/ISysJobLogService.java                                                  |   56 
 jcdm-generator/pom.xml                                                                                                    |   40 
 jcdm-main/src/main/resources/mapper/em/equipmentAlarm/EmEquipmentAlarmMapper.xml                                          |  121 
 jcdm-ui/src/views/dashboard/BarChart.vue                                                                                  |  102 
 jcdm-ui/src/views/monitor/job/index.vue                                                                                   |  513 
 jcdm-main/src/main/java/com/jcdm/main/bs/beatSetting/service/IBsBeatSettingService.java                                   |   61 
 jcdm-ui/src/assets/icons/svg/nested.svg                                                                                   |    1 
 jcdm-system/src/main/java/com/jcdm/system/service/impl/SysMenuServiceImpl.java                                            |  531 
 jcdm-framework/src/main/java/com/jcdm/framework/config/properties/PermitAllUrlProperties.java                             |   73 
 jcdm-main/src/main/java/com/jcdm/main/em/equipmentArchives/mapper/EmEquipmentArchivesMapper.java                          |   61 
 jcdm-framework/src/main/java/com/jcdm/framework/security/filter/JwtAuthenticationTokenFilter.java                         |   44 
 jcdm-common/src/main/java/com/jcdm/common/exception/job/TaskException.java                                                |   34 
 jcdm-main/src/main/java/com/jcdm/main/webservice/Item.java                                                                |   25 
 jcdm-common/src/main/java/com/jcdm/common/filter/XssHttpServletRequestWrapper.java                                        |  111 
 jcdm-generator/src/main/resources/vm/sql/sql.vm                                                                           |   23 
 jcdm-ui/src/api/main/bs/lineInfo/lineInfo.js                                                                              |   44 
 sql/ry_20231130.sql                                                                                                       |  700 
 jcdm-ui/src/api/main/em/equipmentAlarm/equipmentAlarm.js                                                                  |   44 
 jcdm-ui/src/views/components/icons/element-icons.js                                                                       |    3 
 jcdm-main/src/main/java/com/jcdm/main/bs/technologyRouteChild/service/impl/BsTechnologyRouteChildInfoServiceImpl.java     |  100 
 jcdm-main/src/main/java/com/jcdm/main/rm/repairRecord/service/impl/RmRepairRecordServiceImpl.java                         |   96 
 jcdm-ui/src/views/main/om/productionOrde/index.vue                                                                        |  656 
 jcdm-main/src/main/resources/opcua.properties                                                                             |   20 
 jcdm-ui/src/plugins/modal.js                                                                                              |   83 
 jcdm-ui/src/views/system/user/authRole.vue                                                                                |  117 
 jcdm-ui/src/api/main/da/opcuaconfig/opcuaconfig.js                                                                        |   44 
 jcdm-ui/src/assets/404_images/404_cloud.png                                                                               |    0 
 jcdm-main/src/main/java/com/jcdm/main/bs/productBomChild/mapper/BsProductBomChildInfoMapper.java                          |   62 
 jcdm-main/src/main/java/com/jcdm/main/da/paramCollection/controller/DaParamCollectionController.java                      |  103 
 jcdm-ui/src/views/system/dict/index.vue                                                                                   |  347 
 jcdm-ui/src/api/main/da/passingStationCollection/passingStationCollection.js                                              |   44 
 jcdm-ui/src/store/modules/tagsView.js                                                                                     |  228 
 jcdm-main/src/main/java/com/jcdm/main/bs/lineInfo/domain/BsLineInfo.java                                                  |  190 
 jcdm-admin/src/main/java/com/jcdm/MesApplication.java                                                                     |   33 
 jcdm-main/src/main/java/com/jcdm/main/webservice/test.java                                                                |   93 
 jcdm-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml                                                        |   34 
 jcdm-ui/src/assets/icons/svg/rate.svg                                                                                     |    1 
 jcdm-main/src/main/java/com/jcdm/main/bs/formulaChild/service/impl/BsFormulaChildInfoServiceImpl.java                     |  130 
 jcdm-ui/src/views/main/bs/technologyRoute/index.vue                                                                       |  367 
 jcdm-ui/src/assets/icons/svg/user.svg                                                                                     |    1 
 jcdm-ui/src/views/main/bs/ProductBom/index.vue                                                                            |  391 
 jcdm-system/src/main/java/com/jcdm/system/domain/SysRoleDept.java                                                         |   46 
 jcdm-common/src/main/java/com/jcdm/common/core/text/Convert.java                                                          | 1006 
 jcdm-main/src/main/java/com/jcdm/main/bs/technologyRoute/domain/BsTechnologyRouteInfo.java                                |  218 
 jcdm-ui/src/plugins/index.js                                                                                              |   20 
 jcdm-main/src/main/resources/mapper/bs/formulaChild/BsFormulaChildInfoMapper.xml                                          |  185 
 jcdm-main/src/main/resources/mapper/bs/technologyRouteChild/BsTechnologyRouteChildInfoMapper.xml                          |  164 
 jcdm-ui/src/components/ParentView/index.vue                                                                               |    3 
 jcdm-common/src/main/java/com/jcdm/common/utils/uuid/UUID.java                                                            |  484 
 jcdm-ui/src/api/system/dict/type.js                                                                                       |   60 
 jcdm-main/src/main/java/com/jcdm/main/bs/productBom/service/IBsProductBomInfoService.java                                 |   62 
 jcdm-generator/src/main/resources/vm/java/mapper.java.vm                                                                  |   91 
 jcdm-ui/src/assets/icons/svg/pdf.svg                                                                                      |    1 
 jcdm-main/src/main/java/com/jcdm/main/om/productionOrde/domain/OmProductionOrdeInfo.java                                  |  557 
 jcdm-ui/src/assets/icons/svg/server.svg                                                                                   |    1 
 jcdm-main/src/main/java/com/jcdm/main/bs/productBomChild/domain/BsProductBomChildInfo.java                                |  191 
 jcdm-system/src/main/java/com/jcdm/system/mapper/SysDictTypeMapper.java                                                   |   83 
 jcdm-ui/src/assets/icons/svg/redis-list.svg                                                                               |    2 
 jcdm-ui/src/assets/icons/svg/example.svg                                                                                  |    1 
 jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysDept.java                                                 |  203 
 jcdm-ui/src/components/Crontab/month.vue                                                                                  |  114 
 jcdm-main/src/main/java/com/jcdm/main/da/collectionParamConf/controller/DaCollectionParamConfController.java              |   98 
 jcdm-system/src/main/java/com/jcdm/system/service/impl/SysUserServiceImpl.java                                            |  544 
 jcdm-ui/src/views/tool/gen/editTable.vue                                                                                  |  234 
 jcdm-main/src/main/java/com/jcdm/main/bs/productBom/domain/BsProductBomInfo.java                                          |  194 
 jcdm-ui/.eslintignore                                                                                                     |   10 
 jcdm-ui/src/assets/icons/svg/switch.svg                                                                                   |    1 
 jcdm-main/src/main/java/com/jcdm/main/bs/formulaChild/mapper/BsFormulaChildInfoMapper.java                                |   67 
 jcdm-ui/src/assets/icons/svg/message.svg                                                                                  |    1 
 jcdm-ui/src/utils/generator/css.js                                                                                        |   18 
 jcdm-ui/src/views/tool/build/IconsDialog.vue                                                                              |  123 
 jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/cert/KeyStoreLoader.java                                             |  127 
 jcdm-ui/src/views/system/role/authUser.vue                                                                                |  199 
 jcdm-main/src/main/java/com/jcdm/main/bs/lineInfo/service/impl/BsLineInfoServiceImpl.java                                 |  100 
 jcdm-framework/src/main/java/com/jcdm/framework/datasource/DynamicDataSourceContextHolder.java                            |   45 
 jcdm-generator/src/main/resources/vm/java/controller.java.vm                                                              |  115 
 jcdm-ui/src/assets/icons/svg/log.svg                                                                                      |    1 
 jcdm-main/src/main/java/com/jcdm/main/om/workReport/mapper/OmWorkReportMapper.java                                        |   61 
 jcdm-ui/src/api/main/bs/formulaChild/formulaChild.js                                                                      |   73 
 jcdm-main/src/main/java/com/jcdm/main/bs/technologyRouteChild/domain/BsTechnologyRouteChildInfo.java                      |  257 
 jcdm-generator/src/main/resources/vm/java/serviceImpl.java.vm                                                             |  169 
 jcdm-main/src/main/java/com/jcdm/main/bs/productBom/mapper/BsProductBomInfoMapper.java                                    |   63 
 jcdm-ui/src/views/components/icons/svg-icons.js                                                                           |   10 
 jcdm-main/src/main/java/com/jcdm/main/em/equipmentArchives/service/impl/EmEquipmentArchivesServiceImpl.java               |   96 
 jcdm-system/src/main/java/com/jcdm/system/mapper/SysUserRoleMapper.java                                                   |   62 
 jcdm-ui/src/assets/icons/svg/upload.svg                                                                                   |    1 
 jcdm-common/src/main/java/com/jcdm/common/annotation/DataScope.java                                                       |   33 
 jcdm-system/src/main/resources/mapper/system/SysNoticeMapper.xml                                                          |   89 
 jcdm-main/src/main/java/com/jcdm/main/sc/stationConf/service/IScStationConfService.java                                   |   63 
 jcdm-system/src/main/resources/mapper/system/SysConfigMapper.xml                                                          |  117 
 jcdm-ui/src/assets/icons/svg/textarea.svg                                                                                 |    1 
 jcdm-ui/src/plugins/tab.js                                                                                                |   71 
 jcdm-ui/src/layout/index.vue                                                                                              |  111 
 jcdm-ui/src/assets/images/light.svg                                                                                       |   39 
 jcdm-system/src/main/java/com/jcdm/system/service/impl/SysPostServiceImpl.java                                            |  178 
 jcdm-common/src/main/java/com/jcdm/common/utils/spring/SpringUtils.java                                                   |  158 
 jcdm-main/src/main/java/com/jcdm/main/bs/formula/service/IBsFormulaInfoService.java                                       |   61 
 jcdm-main/src/main/java/com/jcdm/main/bs/processFile/mapper/BsProcessFileMapper.java                                      |   61 
 jcdm-common/src/main/java/com/jcdm/common/utils/SecurityUtils.java                                                        |  178 
 jcdm-ui/src/api/main/bs/beatSetting/beatSetting.js                                                                        |   44 
 jcdm-admin/src/main/java/com/jcdm/web/controller/monitor/SysLogininforController.java                                     |   82 
 jcdm-common/src/main/java/com/jcdm/common/utils/DictUtils.java                                                            |  204 
 jcdm-ui/src/components/Screenfull/index.vue                                                                               |   57 
 jcdm-framework/src/main/java/com/jcdm/framework/security/handle/LogoutSuccessHandlerImpl.java                             |   52 
 jcdm-ui/src/api/main/da/paramCollection/paramCollection.js                                                                |   44 
 jcdm-ui/src/assets/styles/index.scss                                                                                      |  186 
 jcdm-main/src/main/java/com/jcdm/main/da/paramCollection/service/IDaParamCollectionService.java                           |   62 
 jcdm-ui/src/directive/dialog/dragWidth.js                                                                                 |   29 
 jcdm-common/src/main/java/com/jcdm/common/utils/bean/BeanUtils.java                                                       |  110 
 jcdm-framework/src/main/java/com/jcdm/framework/config/DruidConfig.java                                                   |  126 
 jcdm-main/src/main/resources/mapper/bs/technologyRoute/BsTechnologyRouteInfoMapper.xml                                    |  123 
 jcdm-ui/README.md                                                                                                         |   30 
 jcdm-ui/src/assets/icons/svg/number.svg                                                                                   |    1 
 jcdm-common/src/main/java/com/jcdm/common/core/domain/R.java                                                              |  115 
 jcdm-ui/src/store/index.js                                                                                                |   25 
 jcdm-ui/src/views/main/bs/lineInfo/index.vue                                                                              |  413 
 jcdm-common/src/main/java/com/jcdm/common/utils/bean/BeanValidators.java                                                  |   24 
 jcdm-ui/src/assets/icons/svg/dashboard.svg                                                                                |    1 
 jcdm-ui/src/components/Crontab/result.vue                                                                                 |  559 
 jcdm-main/src/main/java/com/jcdm/main/sc/stationConf/controller/ScStationConfController.java                              |  118 
 jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/init/Properties.java                                                 |   57 
 jcdm-common/src/main/java/com/jcdm/common/utils/file/FileTypeUtils.java                                                   |   76 
 jcdm-main/src/main/resources/mapper/bs/processes/BsProcessesInfoMapper.xml                                                |  117 
 jcdm-main/src/main/java/com/jcdm/main/em/equipmentStatus/domain/EmEquipmentStatus.java                                    |  162 
 jcdm-main/src/main/java/com/jcdm/main/om/workReport/service/impl/OmWorkReportServiceImpl.java                             |   96 
 jcdm-system/src/main/resources/mapper/system/SysDictTypeMapper.xml                                                        |  108 
 jcdm-ui/src/assets/icons/svg/search.svg                                                                                   |    1 
 jcdm-common/src/main/java/com/jcdm/common/core/page/TableDataInfo.java                                                    |   85 
 jcdm-ui/src/views/main/bs/formula/index.vue                                                                               |  353 
 jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysMenu.java                                                 |  259 
 jcdm-framework/src/main/java/com/jcdm/framework/web/service/UserDetailsServiceImpl.java                                   |   66 
 jcdm-ui/src/views/dashboard/PanelGroup.vue                                                                                |  181 
 jcdm-generator/src/main/resources/vm/xml/mapper.xml.vm                                                                    |  135 
 jcdm-system/src/main/resources/mapper/system/SysMenuMapper.xml                                                            |  203 
 jcdm-ui/src/assets/images/login-background.jpg                                                                            |    0 
 jcdm-ui/src/assets/icons/svg/zip.svg                                                                                      |    1 
 jcdm-ui/src/api/main/bs/processFile/processFile.js                                                                        |   44 
 jcdm-system/src/main/java/com/jcdm/system/mapper/SysRoleMenuMapper.java                                                   |   44 
 jcdm-ui/src/store/getters.js                                                                                              |   19 
 jcdm-framework/src/main/java/com/jcdm/framework/config/FilterConfig.java                                                  |   58 
 jcdm-system/src/main/java/com/jcdm/system/service/ISysMenuService.java                                                    |  144 
 jcdm-ui/.editorconfig                                                                                                     |   22 
 jcdm-common/src/main/java/com/jcdm/common/core/domain/BaseEntity.java                                                     |  118 
 jcdm-main/src/main/java/com/jcdm/main/bs/material/service/impl/BsMaterialInfoServiceImpl.java                             |   94 
 jcdm-main/src/main/java/com/jcdm/main/em/equipmentStatus/service/IEmEquipmentStatusService.java                           |   61 
 jcdm-ui/src/views/tool/gen/genInfoForm.vue                                                                                |  312 
 jcdm-common/src/main/java/com/jcdm/common/utils/poi/ExcelHandlerAdapter.java                                              |   24 
 jcdm-framework/src/main/java/com/jcdm/framework/manager/factory/AsyncFactory.java                                         |  102 
 jcdm-ui/src/assets/icons/svg/form.svg                                                                                     |    1 
 jcdm-ui/src/assets/icons/svg/language.svg                                                                                 |    1 
 jcdm-ui/src/assets/icons/svg/people.svg                                                                                   |    1 
 jcdm-ui/src/views/main/om/workReport/index.vue                                                                            |  378 
 jcdm-generator/src/main/java/com/jcdm/generator/service/IGenTableColumnService.java                                       |   44 
 jcdm-ui/src/views/error/404.vue                                                                                           |  233 
 jcdm-generator/src/main/resources/vm/js/api.js.vm                                                                         |   44 
 jcdm-main/src/main/resources/mapper/rm/repairData/RmRepairDataMapper.xml                                                  |  131 
 jcdm-ui/babel.config.js                                                                                                   |   13 
 jcdm-common/src/main/java/com/jcdm/common/annotation/RepeatSubmit.java                                                    |   31 
 jcdm-admin/src/main/java/com/jcdm/web/controller/monitor/CacheController.java                                             |  120 
 jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/mapper/DaPassingStationCollectionMapper.java            |   62 
 jcdm-ui/src/utils/validate.js                                                                                             |   80 
 jcdm-common/src/main/java/com/jcdm/common/annotation/DataSource.java                                                      |   28 
 jcdm-common/src/main/java/com/jcdm/common/utils/LogUtils.java                                                             |   18 
 jcdm-system/pom.xml                                                                                                       |   28 
 jcdm-common/src/main/java/com/jcdm/common/core/text/StrFormatter.java                                                     |   92 
 jcdm-system/src/main/java/com/jcdm/system/service/ISysNoticeService.java                                                  |   60 
 jcdm-ui/src/assets/icons/svg/tree.svg                                                                                     |    1 
 jcdm-main/src/main/java/com/jcdm/main/bs/workshop/controller/BsWorkshopInfoController.java                                |  105 
 jcdm-ui/src/utils/errorCode.js                                                                                            |    6 
 824 files changed, 95,127 insertions(+), 0 deletions(-)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ed8368a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,47 @@
+######################################################################
+# Build Tools
+
+.gradle
+/build/
+!gradle/wrapper/gradle-wrapper.jar
+
+target/
+!.mvn/wrapper/maven-wrapper.jar
+
+######################################################################
+# IDE
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### JRebel ###
+rebel.xml
+
+### NetBeans ###
+nbproject/private/
+build/*
+nbbuild/
+dist/
+nbdist/
+.nb-gradle/
+
+######################################################################
+# Others
+*.log
+*.xml.versionsBackup
+*.swp
+
+!*/build/*.java
+!*/build/*.html
+!*/build/*.xml
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..a75f0aa
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2018 Jcdm
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/bin/clean.bat b/bin/clean.bat
new file mode 100644
index 0000000..24c0974
--- /dev/null
+++ b/bin/clean.bat
@@ -0,0 +1,12 @@
+@echo off
+echo.
+echo [信息] 清理工程target生成路径。
+echo.
+
+%~d0
+cd %~dp0
+
+cd ..
+call mvn clean
+
+pause
\ No newline at end of file
diff --git a/bin/package.bat b/bin/package.bat
new file mode 100644
index 0000000..c693ec0
--- /dev/null
+++ b/bin/package.bat
@@ -0,0 +1,12 @@
+@echo off
+echo.
+echo [信息] 打包Web工程,生成war/jar包文件。
+echo.
+
+%~d0
+cd %~dp0
+
+cd ..
+call mvn clean package -Dmaven.test.skip=true
+
+pause
\ No newline at end of file
diff --git a/bin/run.bat b/bin/run.bat
new file mode 100644
index 0000000..4cdd919
--- /dev/null
+++ b/bin/run.bat
@@ -0,0 +1,14 @@
+@echo off
+echo.
+echo [信息] 使用Jar命令运行Web工程。
+echo.
+
+cd %~dp0
+cd ../jcdm-admin/target
+
+set JAVA_OPTS=-Xms256m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m
+
+java -jar %JAVA_OPTS% jcdm-admin.jar
+
+cd bin
+pause
\ No newline at end of file
diff --git "a/doc/\342\225\232\342\214\240\342\225\245\342\224\224\342\225\227\342\225\226\342\225\233\342\224\202\342\225\251\342\225\243\342\225\231\342\224\234\342\225\251\342\225\223\342\226\223\303\237.docx" "b/doc/\342\225\232\342\214\240\342\225\245\342\224\224\342\225\227\342\225\226\342\225\233\342\224\202\342\225\251\342\225\243\342\225\231\342\224\234\342\225\251\342\225\223\342\226\223\303\237.docx"
new file mode 100644
index 0000000..9e4daef
--- /dev/null
+++ "b/doc/\342\225\232\342\214\240\342\225\245\342\224\224\342\225\227\342\225\226\342\225\233\342\224\202\342\225\251\342\225\243\342\225\231\342\224\234\342\225\251\342\225\223\342\226\223\303\237.docx"
Binary files differ
diff --git a/jcdm-admin/pom.xml b/jcdm-admin/pom.xml
new file mode 100644
index 0000000..d6b3f0d
--- /dev/null
+++ b/jcdm-admin/pom.xml
@@ -0,0 +1,108 @@
+<?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">
+    <parent>
+        <artifactId>jcdm</artifactId>
+        <groupId>com.jcdm</groupId>
+        <version>3.8.6</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <packaging>jar</packaging>
+    <artifactId>jcdm-admin</artifactId>
+
+    <description>
+        web鏈嶅姟鍏ュ彛
+    </description>
+
+    <dependencies>
+
+        <!-- spring-boot-devtools -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-devtools</artifactId>
+            <optional>true</optional> <!-- 琛ㄧず渚濊禆涓嶄細浼犻�� -->
+        </dependency>
+
+        <!-- swagger3-->
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-boot-starter</artifactId>
+        </dependency>
+
+        <!-- 闃叉杩涘叆swagger椤甸潰鎶ョ被鍨嬭浆鎹㈤敊璇紝鎺掗櫎3.0.0涓殑寮曠敤锛屾墜鍔ㄥ鍔�1.6.2鐗堟湰 -->
+        <dependency>
+            <groupId>io.swagger</groupId>
+            <artifactId>swagger-models</artifactId>
+            <version>1.6.2</version>
+        </dependency>
+
+         <!-- Mysql椹卞姩鍖� -->
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+        </dependency>
+
+        <!--sqlserver鏁版嵁搴撻厤缃�-->
+        <dependency>
+            <groupId>com.microsoft.sqlserver</groupId>
+            <artifactId>mssql-jdbc</artifactId>
+        </dependency>
+
+        <!-- 鏍稿績妯″潡-->
+        <dependency>
+            <groupId>com.jcdm</groupId>
+            <artifactId>jcdm-framework</artifactId>
+        </dependency>
+
+        <!-- 瀹氭椂浠诲姟-->
+        <dependency>
+            <groupId>com.jcdm</groupId>
+            <artifactId>jcdm-quartz</artifactId>
+        </dependency>
+
+        <!-- 浠g爜鐢熸垚-->
+        <dependency>
+            <groupId>com.jcdm</groupId>
+            <artifactId>jcdm-generator</artifactId>
+        </dependency>
+
+        <!-- JCDM妯″潡-->
+        <dependency>
+            <groupId>com.jcdm</groupId>
+            <artifactId>jcdm-main</artifactId>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>2.5.15</version>
+                <configuration>
+                    <fork>true</fork> <!-- 濡傛灉娌℃湁璇ラ厤缃紝devtools涓嶄細鐢熸晥 -->
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>   
+                <groupId>org.apache.maven.plugins</groupId>   
+                <artifactId>maven-war-plugin</artifactId>   
+                <version>3.1.0</version>   
+                <configuration>
+                    <failOnMissingWebXml>false</failOnMissingWebXml>
+                    <warName>${project.artifactId}</warName>
+                </configuration>   
+           </plugin>   
+        </plugins>
+        <finalName>${project.artifactId}</finalName>
+    </build>
+
+</project>
\ No newline at end of file
diff --git a/jcdm-admin/src/main/java/com/jcdm/MesApplication.java b/jcdm-admin/src/main/java/com/jcdm/MesApplication.java
new file mode 100644
index 0000000..1313000
--- /dev/null
+++ b/jcdm-admin/src/main/java/com/jcdm/MesApplication.java
@@ -0,0 +1,33 @@
+package com.jcdm;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+
+/**
+ * 鍚姩绋嬪簭
+ * 
+ * @author jc
+ */
+
+
+@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
+public class MesApplication
+{
+    public static void main(String[] args)
+    {
+        // System.setProperty("spring.devtools.restart.enabled", "false");
+        SpringApplication.run(MesApplication.class, args);
+        System.out.println("(鈾モ棤鈥库棤)锞夛緸  绯荤粺鍚姩鎴愬姛   醿�(麓凇`醿�)锞�  \n" /*+
+                " .-------.       ____     __        \n" +
+                " |  _ _   \\      \\   \\   /  /    \n" +
+                " | ( ' )  |       \\  _. /  '       \n" +
+                " |(_ o _) /        _( )_ .'         \n" +
+                " | (_,_).' __  ___(_ o _)'          \n" +
+                " |  |\\ \\  |  ||   |(_,_)'         \n" +
+                " |  | \\ `'   /|   `-'  /           \n" +
+                " |  |  \\    /  \\      /           \n" +
+                " ''-'   `'-'    `-..-'              " */
+                );
+    }
+}
diff --git a/jcdm-admin/src/main/java/com/jcdm/MesServletInitializer.java b/jcdm-admin/src/main/java/com/jcdm/MesServletInitializer.java
new file mode 100644
index 0000000..1da5365
--- /dev/null
+++ b/jcdm-admin/src/main/java/com/jcdm/MesServletInitializer.java
@@ -0,0 +1,18 @@
+package com.jcdm;
+
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+
+/**
+ * web瀹瑰櫒涓繘琛岄儴缃�
+ * 
+ * @author jc
+ */
+public class MesServletInitializer extends SpringBootServletInitializer
+{
+    @Override
+    protected SpringApplicationBuilder configure(SpringApplicationBuilder application)
+    {
+        return application.sources(MesApplication.class);
+    }
+}
diff --git a/jcdm-admin/src/main/java/com/jcdm/web/controller/common/CaptchaController.java b/jcdm-admin/src/main/java/com/jcdm/web/controller/common/CaptchaController.java
new file mode 100644
index 0000000..3d75968
--- /dev/null
+++ b/jcdm-admin/src/main/java/com/jcdm/web/controller/common/CaptchaController.java
@@ -0,0 +1,94 @@
+package com.jcdm.web.controller.common;
+
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+import javax.annotation.Resource;
+import javax.imageio.ImageIO;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.FastByteArrayOutputStream;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.google.code.kaptcha.Producer;
+import com.jcdm.common.config.MesConfig;
+import com.jcdm.common.constant.CacheConstants;
+import com.jcdm.common.constant.Constants;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.core.redis.RedisCache;
+import com.jcdm.common.utils.sign.Base64;
+import com.jcdm.common.utils.uuid.IdUtils;
+import com.jcdm.system.service.ISysConfigService;
+
+/**
+ * 楠岃瘉鐮佹搷浣滃鐞�
+ * 
+ * @author jc
+ */
+@RestController
+public class CaptchaController
+{
+    @Resource(name = "captchaProducer")
+    private Producer captchaProducer;
+
+    @Resource(name = "captchaProducerMath")
+    private Producer captchaProducerMath;
+
+    @Autowired
+    private RedisCache redisCache;
+    
+    @Autowired
+    private ISysConfigService configService;
+    /**
+     * 鐢熸垚楠岃瘉鐮�
+     */
+    @GetMapping("/captchaImage")
+    public AjaxResult getCode(HttpServletResponse response) throws IOException
+    {
+        AjaxResult ajax = AjaxResult.success();
+        boolean captchaEnabled = configService.selectCaptchaEnabled();
+        ajax.put("captchaEnabled", captchaEnabled);
+        if (!captchaEnabled)
+        {
+            return ajax;
+        }
+
+        // 淇濆瓨楠岃瘉鐮佷俊鎭�
+        String uuid = IdUtils.simpleUUID();
+        String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid;
+
+        String capStr = null, code = null;
+        BufferedImage image = null;
+
+        // 鐢熸垚楠岃瘉鐮�
+        String captchaType = MesConfig.getCaptchaType();
+        if ("math".equals(captchaType))
+        {
+            String capText = captchaProducerMath.createText();
+            capStr = capText.substring(0, capText.lastIndexOf("@"));
+            code = capText.substring(capText.lastIndexOf("@") + 1);
+            image = captchaProducerMath.createImage(capStr);
+        }
+        else if ("char".equals(captchaType))
+        {
+            capStr = code = captchaProducer.createText();
+            image = captchaProducer.createImage(capStr);
+        }
+
+        redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
+        // 杞崲娴佷俊鎭啓鍑�
+        FastByteArrayOutputStream os = new FastByteArrayOutputStream();
+        try
+        {
+            ImageIO.write(image, "jpg", os);
+        }
+        catch (IOException e)
+        {
+            return AjaxResult.error(e.getMessage());
+        }
+
+        ajax.put("uuid", uuid);
+        ajax.put("img", Base64.encode(os.toByteArray()));
+        return ajax;
+    }
+}
diff --git a/jcdm-admin/src/main/java/com/jcdm/web/controller/common/CommonController.java b/jcdm-admin/src/main/java/com/jcdm/web/controller/common/CommonController.java
new file mode 100644
index 0000000..8a864ff
--- /dev/null
+++ b/jcdm-admin/src/main/java/com/jcdm/web/controller/common/CommonController.java
@@ -0,0 +1,163 @@
+package com.jcdm.web.controller.common;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+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;
+import org.springframework.web.multipart.MultipartFile;
+import com.jcdm.common.config.MesConfig;
+import com.jcdm.common.constant.Constants;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.common.utils.file.FileUploadUtils;
+import com.jcdm.common.utils.file.FileUtils;
+import com.jcdm.framework.config.ServerConfig;
+
+/**
+ * 閫氱敤璇锋眰澶勭悊
+ * 
+ * @author jc
+ */
+@RestController
+@RequestMapping("/common")
+public class CommonController
+{
+    private static final Logger log = LoggerFactory.getLogger(CommonController.class);
+
+    @Autowired
+    private ServerConfig serverConfig;
+
+    private static final String FILE_DELIMETER = ",";
+
+    /**
+     * 閫氱敤涓嬭浇璇锋眰
+     * 
+     * @param fileName 鏂囦欢鍚嶇О
+     * @param delete 鏄惁鍒犻櫎
+     */
+    @GetMapping("/download")
+    public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request)
+    {
+        try
+        {
+            if (!FileUtils.checkAllowDownload(fileName))
+            {
+                throw new Exception(StringUtils.format("鏂囦欢鍚嶇О({})闈炴硶锛屼笉鍏佽涓嬭浇銆� ", fileName));
+            }
+            String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
+            String filePath = MesConfig.getDownloadPath() + fileName;
+
+            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
+            FileUtils.setAttachmentResponseHeader(response, realFileName);
+            FileUtils.writeBytes(filePath, response.getOutputStream());
+            if (delete)
+            {
+                FileUtils.deleteFile(filePath);
+            }
+        }
+        catch (Exception e)
+        {
+            log.error("涓嬭浇鏂囦欢澶辫触", e);
+        }
+    }
+
+    /**
+     * 閫氱敤涓婁紶璇锋眰锛堝崟涓級
+     */
+    @PostMapping("/upload")
+    public AjaxResult uploadFile(MultipartFile file) throws Exception
+    {
+        try
+        {
+            // 涓婁紶鏂囦欢璺緞
+            String filePath = MesConfig.getUploadPath();
+            // 涓婁紶骞惰繑鍥炴柊鏂囦欢鍚嶇О
+            String fileName = FileUploadUtils.upload(filePath, file);
+            String url = serverConfig.getUrl() + fileName;
+            AjaxResult ajax = AjaxResult.success();
+            ajax.put("url", url);
+            ajax.put("fileName", fileName);
+            ajax.put("newFileName", FileUtils.getName(fileName));
+            ajax.put("originalFilename", file.getOriginalFilename());
+            return ajax;
+        }
+        catch (Exception e)
+        {
+            return AjaxResult.error(e.getMessage());
+        }
+    }
+
+    /**
+     * 閫氱敤涓婁紶璇锋眰锛堝涓級
+     */
+    @PostMapping("/uploads")
+    public AjaxResult uploadFiles(List<MultipartFile> files) throws Exception
+    {
+        try
+        {
+            // 涓婁紶鏂囦欢璺緞
+            String filePath = MesConfig.getUploadPath();
+            List<String> urls = new ArrayList<String>();
+            List<String> fileNames = new ArrayList<String>();
+            List<String> newFileNames = new ArrayList<String>();
+            List<String> originalFilenames = new ArrayList<String>();
+            for (MultipartFile file : files)
+            {
+                // 涓婁紶骞惰繑鍥炴柊鏂囦欢鍚嶇О
+                String fileName = FileUploadUtils.upload(filePath, file);
+                String url = serverConfig.getUrl() + fileName;
+                urls.add(url);
+                fileNames.add(fileName);
+                newFileNames.add(FileUtils.getName(fileName));
+                originalFilenames.add(file.getOriginalFilename());
+            }
+            AjaxResult ajax = AjaxResult.success();
+            ajax.put("urls", StringUtils.join(urls, FILE_DELIMETER));
+            ajax.put("fileNames", StringUtils.join(fileNames, FILE_DELIMETER));
+            ajax.put("newFileNames", StringUtils.join(newFileNames, FILE_DELIMETER));
+            ajax.put("originalFilenames", StringUtils.join(originalFilenames, FILE_DELIMETER));
+            return ajax;
+        }
+        catch (Exception e)
+        {
+            return AjaxResult.error(e.getMessage());
+        }
+    }
+
+    /**
+     * 鏈湴璧勬簮閫氱敤涓嬭浇
+     */
+    @GetMapping("/download/resource")
+    public void resourceDownload(String resource, HttpServletRequest request, HttpServletResponse response)
+            throws Exception
+    {
+        try
+        {
+            if (!FileUtils.checkAllowDownload(resource))
+            {
+                throw new Exception(StringUtils.format("璧勬簮鏂囦欢({})闈炴硶锛屼笉鍏佽涓嬭浇銆� ", resource));
+            }
+            // 鏈湴璧勬簮璺緞
+            String localPath = MesConfig.getProfile();
+            // 鏁版嵁搴撹祫婧愬湴鍧�
+            String downloadPath = localPath + StringUtils.substringAfter(resource, Constants.RESOURCE_PREFIX);
+            // 涓嬭浇鍚嶇О
+            String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
+            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
+            FileUtils.setAttachmentResponseHeader(response, downloadName);
+            FileUtils.writeBytes(downloadPath, response.getOutputStream());
+        }
+        catch (Exception e)
+        {
+            log.error("涓嬭浇鏂囦欢澶辫触", e);
+        }
+    }
+}
diff --git a/jcdm-admin/src/main/java/com/jcdm/web/controller/monitor/CacheController.java b/jcdm-admin/src/main/java/com/jcdm/web/controller/monitor/CacheController.java
new file mode 100644
index 0000000..8a1a119
--- /dev/null
+++ b/jcdm-admin/src/main/java/com/jcdm/web/controller/monitor/CacheController.java
@@ -0,0 +1,120 @@
+package com.jcdm.web.controller.monitor;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisCallback;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.constant.CacheConstants;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.system.domain.SysCache;
+
+/**
+ * 缂撳瓨鐩戞帶
+ * 
+ * @author jc
+ */
+@RestController
+@RequestMapping("/monitor/cache")
+public class CacheController
+{
+    @Autowired
+    private RedisTemplate<String, String> redisTemplate;
+
+    private final static List<SysCache> caches = new ArrayList<SysCache>();
+    {
+        caches.add(new SysCache(CacheConstants.LOGIN_TOKEN_KEY, "鐢ㄦ埛淇℃伅"));
+        caches.add(new SysCache(CacheConstants.SYS_CONFIG_KEY, "閰嶇疆淇℃伅"));
+        caches.add(new SysCache(CacheConstants.SYS_DICT_KEY, "鏁版嵁瀛楀吀"));
+        caches.add(new SysCache(CacheConstants.CAPTCHA_CODE_KEY, "楠岃瘉鐮�"));
+        caches.add(new SysCache(CacheConstants.REPEAT_SUBMIT_KEY, "闃查噸鎻愪氦"));
+        caches.add(new SysCache(CacheConstants.RATE_LIMIT_KEY, "闄愭祦澶勭悊"));
+        caches.add(new SysCache(CacheConstants.PWD_ERR_CNT_KEY, "瀵嗙爜閿欒娆℃暟"));
+    }
+
+    @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
+    @GetMapping()
+    public AjaxResult getInfo() throws Exception
+    {
+        Properties info = (Properties) redisTemplate.execute((RedisCallback<Object>) connection -> connection.info());
+        Properties commandStats = (Properties) redisTemplate.execute((RedisCallback<Object>) connection -> connection.info("commandstats"));
+        Object dbSize = redisTemplate.execute((RedisCallback<Object>) connection -> connection.dbSize());
+
+        Map<String, Object> result = new HashMap<>(3);
+        result.put("info", info);
+        result.put("dbSize", dbSize);
+
+        List<Map<String, String>> pieList = new ArrayList<>();
+        commandStats.stringPropertyNames().forEach(key -> {
+            Map<String, String> data = new HashMap<>(2);
+            String property = commandStats.getProperty(key);
+            data.put("name", StringUtils.removeStart(key, "cmdstat_"));
+            data.put("value", StringUtils.substringBetween(property, "calls=", ",usec"));
+            pieList.add(data);
+        });
+        result.put("commandStats", pieList);
+        return AjaxResult.success(result);
+    }
+
+    @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
+    @GetMapping("/getNames")
+    public AjaxResult cache()
+    {
+        return AjaxResult.success(caches);
+    }
+
+    @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
+    @GetMapping("/getKeys/{cacheName}")
+    public AjaxResult getCacheKeys(@PathVariable String cacheName)
+    {
+        Set<String> cacheKeys = redisTemplate.keys(cacheName + "*");
+        return AjaxResult.success(cacheKeys);
+    }
+
+    @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
+    @GetMapping("/getValue/{cacheName}/{cacheKey}")
+    public AjaxResult getCacheValue(@PathVariable String cacheName, @PathVariable String cacheKey)
+    {
+        String cacheValue = redisTemplate.opsForValue().get(cacheKey);
+        SysCache sysCache = new SysCache(cacheName, cacheKey, cacheValue);
+        return AjaxResult.success(sysCache);
+    }
+
+    @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
+    @DeleteMapping("/clearCacheName/{cacheName}")
+    public AjaxResult clearCacheName(@PathVariable String cacheName)
+    {
+        Collection<String> cacheKeys = redisTemplate.keys(cacheName + "*");
+        redisTemplate.delete(cacheKeys);
+        return AjaxResult.success();
+    }
+
+    @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
+    @DeleteMapping("/clearCacheKey/{cacheKey}")
+    public AjaxResult clearCacheKey(@PathVariable String cacheKey)
+    {
+        redisTemplate.delete(cacheKey);
+        return AjaxResult.success();
+    }
+
+    @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
+    @DeleteMapping("/clearCacheAll")
+    public AjaxResult clearCacheAll()
+    {
+        Collection<String> cacheKeys = redisTemplate.keys("*");
+        redisTemplate.delete(cacheKeys);
+        return AjaxResult.success();
+    }
+}
diff --git a/jcdm-admin/src/main/java/com/jcdm/web/controller/monitor/ServerController.java b/jcdm-admin/src/main/java/com/jcdm/web/controller/monitor/ServerController.java
new file mode 100644
index 0000000..8f8f2a5
--- /dev/null
+++ b/jcdm-admin/src/main/java/com/jcdm/web/controller/monitor/ServerController.java
@@ -0,0 +1,27 @@
+package com.jcdm.web.controller.monitor;
+
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.framework.web.domain.Server;
+
+/**
+ * 鏈嶅姟鍣ㄧ洃鎺�
+ * 
+ * @author jc
+ */
+@RestController
+@RequestMapping("/monitor/server")
+public class ServerController
+{
+    @PreAuthorize("@ss.hasPermi('monitor:server:list')")
+    @GetMapping()
+    public AjaxResult getInfo() throws Exception
+    {
+        Server server = new Server();
+        server.copyTo();
+        return AjaxResult.success(server);
+    }
+}
diff --git a/jcdm-admin/src/main/java/com/jcdm/web/controller/monitor/SysLogininforController.java b/jcdm-admin/src/main/java/com/jcdm/web/controller/monitor/SysLogininforController.java
new file mode 100644
index 0000000..5ca5846
--- /dev/null
+++ b/jcdm-admin/src/main/java/com/jcdm/web/controller/monitor/SysLogininforController.java
@@ -0,0 +1,82 @@
+package com.jcdm.web.controller.monitor;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.core.page.TableDataInfo;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.common.utils.poi.ExcelUtil;
+import com.jcdm.framework.web.service.SysPasswordService;
+import com.jcdm.system.domain.SysLogininfor;
+import com.jcdm.system.service.ISysLogininforService;
+
+/**
+ * 绯荤粺璁块棶璁板綍
+ * 
+ * @author jc
+ */
+@RestController
+@RequestMapping("/monitor/logininfor")
+public class SysLogininforController extends BaseController
+{
+    @Autowired
+    private ISysLogininforService logininforService;
+
+    @Autowired
+    private SysPasswordService passwordService;
+
+    @PreAuthorize("@ss.hasPermi('monitor:logininfor:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(SysLogininfor logininfor)
+    {
+        startPage();
+        List<SysLogininfor> list = logininforService.selectLogininforList(logininfor);
+        return getDataTable(list);
+    }
+
+    @Log(title = "鐧诲綍鏃ュ織", businessType = BusinessType.EXPORT)
+    @PreAuthorize("@ss.hasPermi('monitor:logininfor:export')")
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, SysLogininfor logininfor)
+    {
+        List<SysLogininfor> list = logininforService.selectLogininforList(logininfor);
+        ExcelUtil<SysLogininfor> util = new ExcelUtil<SysLogininfor>(SysLogininfor.class);
+        util.exportExcel(response, list, "鐧诲綍鏃ュ織");
+    }
+
+    @PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')")
+    @Log(title = "鐧诲綍鏃ュ織", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{infoIds}")
+    public AjaxResult remove(@PathVariable Long[] infoIds)
+    {
+        return toAjax(logininforService.deleteLogininforByIds(infoIds));
+    }
+
+    @PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')")
+    @Log(title = "鐧诲綍鏃ュ織", businessType = BusinessType.CLEAN)
+    @DeleteMapping("/clean")
+    public AjaxResult clean()
+    {
+        logininforService.cleanLogininfor();
+        return success();
+    }
+
+    @PreAuthorize("@ss.hasPermi('monitor:logininfor:unlock')")
+    @Log(title = "璐︽埛瑙i攣", businessType = BusinessType.OTHER)
+    @GetMapping("/unlock/{userName}")
+    public AjaxResult unlock(@PathVariable("userName") String userName)
+    {
+        passwordService.clearLoginRecordCache(userName);
+        return success();
+    }
+}
diff --git a/jcdm-admin/src/main/java/com/jcdm/web/controller/monitor/SysOperlogController.java b/jcdm-admin/src/main/java/com/jcdm/web/controller/monitor/SysOperlogController.java
new file mode 100644
index 0000000..864b06d
--- /dev/null
+++ b/jcdm-admin/src/main/java/com/jcdm/web/controller/monitor/SysOperlogController.java
@@ -0,0 +1,69 @@
+package com.jcdm.web.controller.monitor;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.core.page.TableDataInfo;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.common.utils.poi.ExcelUtil;
+import com.jcdm.system.domain.SysOperLog;
+import com.jcdm.system.service.ISysOperLogService;
+
+/**
+ * 鎿嶄綔鏃ュ織璁板綍
+ * 
+ * @author jc
+ */
+@RestController
+@RequestMapping("/monitor/operlog")
+public class SysOperlogController extends BaseController
+{
+    @Autowired
+    private ISysOperLogService operLogService;
+
+    @PreAuthorize("@ss.hasPermi('monitor:operlog:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(SysOperLog operLog)
+    {
+        startPage();
+        List<SysOperLog> list = operLogService.selectOperLogList(operLog);
+        return getDataTable(list);
+    }
+
+    @Log(title = "鎿嶄綔鏃ュ織", businessType = BusinessType.EXPORT)
+    @PreAuthorize("@ss.hasPermi('monitor:operlog:export')")
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, SysOperLog operLog)
+    {
+        List<SysOperLog> list = operLogService.selectOperLogList(operLog);
+        ExcelUtil<SysOperLog> util = new ExcelUtil<SysOperLog>(SysOperLog.class);
+        util.exportExcel(response, list, "鎿嶄綔鏃ュ織");
+    }
+
+    @Log(title = "鎿嶄綔鏃ュ織", businessType = BusinessType.DELETE)
+    @PreAuthorize("@ss.hasPermi('monitor:operlog:remove')")
+    @DeleteMapping("/{operIds}")
+    public AjaxResult remove(@PathVariable Long[] operIds)
+    {
+        return toAjax(operLogService.deleteOperLogByIds(operIds));
+    }
+
+    @Log(title = "鎿嶄綔鏃ュ織", businessType = BusinessType.CLEAN)
+    @PreAuthorize("@ss.hasPermi('monitor:operlog:remove')")
+    @DeleteMapping("/clean")
+    public AjaxResult clean()
+    {
+        operLogService.cleanOperLog();
+        return success();
+    }
+}
diff --git a/jcdm-admin/src/main/java/com/jcdm/web/controller/monitor/SysUserOnlineController.java b/jcdm-admin/src/main/java/com/jcdm/web/controller/monitor/SysUserOnlineController.java
new file mode 100644
index 0000000..6976f6a
--- /dev/null
+++ b/jcdm-admin/src/main/java/com/jcdm/web/controller/monitor/SysUserOnlineController.java
@@ -0,0 +1,83 @@
+package com.jcdm.web.controller.monitor;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.constant.CacheConstants;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.core.domain.model.LoginUser;
+import com.jcdm.common.core.page.TableDataInfo;
+import com.jcdm.common.core.redis.RedisCache;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.system.domain.SysUserOnline;
+import com.jcdm.system.service.ISysUserOnlineService;
+
+/**
+ * 鍦ㄧ嚎鐢ㄦ埛鐩戞帶
+ * 
+ * @author jc
+ */
+@RestController
+@RequestMapping("/monitor/online")
+public class SysUserOnlineController extends BaseController
+{
+    @Autowired
+    private ISysUserOnlineService userOnlineService;
+
+    @Autowired
+    private RedisCache redisCache;
+
+    @PreAuthorize("@ss.hasPermi('monitor:online:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(String ipaddr, String userName)
+    {
+        Collection<String> keys = redisCache.keys(CacheConstants.LOGIN_TOKEN_KEY + "*");
+        List<SysUserOnline> userOnlineList = new ArrayList<SysUserOnline>();
+        for (String key : keys)
+        {
+            LoginUser user = redisCache.getCacheObject(key);
+            if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName))
+            {
+                userOnlineList.add(userOnlineService.selectOnlineByInfo(ipaddr, userName, user));
+            }
+            else if (StringUtils.isNotEmpty(ipaddr))
+            {
+                userOnlineList.add(userOnlineService.selectOnlineByIpaddr(ipaddr, user));
+            }
+            else if (StringUtils.isNotEmpty(userName) && StringUtils.isNotNull(user.getUser()))
+            {
+                userOnlineList.add(userOnlineService.selectOnlineByUserName(userName, user));
+            }
+            else
+            {
+                userOnlineList.add(userOnlineService.loginUserToUserOnline(user));
+            }
+        }
+        Collections.reverse(userOnlineList);
+        userOnlineList.removeAll(Collections.singleton(null));
+        return getDataTable(userOnlineList);
+    }
+
+    /**
+     * 寮洪��鐢ㄦ埛
+     */
+    @PreAuthorize("@ss.hasPermi('monitor:online:forceLogout')")
+    @Log(title = "鍦ㄧ嚎鐢ㄦ埛", businessType = BusinessType.FORCE)
+    @DeleteMapping("/{tokenId}")
+    public AjaxResult forceLogout(@PathVariable String tokenId)
+    {
+        redisCache.deleteObject(CacheConstants.LOGIN_TOKEN_KEY + tokenId);
+        return success();
+    }
+}
diff --git a/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysConfigController.java b/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysConfigController.java
new file mode 100644
index 0000000..d249066
--- /dev/null
+++ b/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysConfigController.java
@@ -0,0 +1,133 @@
+package com.jcdm.web.controller.system;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.core.page.TableDataInfo;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.common.utils.poi.ExcelUtil;
+import com.jcdm.system.domain.SysConfig;
+import com.jcdm.system.service.ISysConfigService;
+
+/**
+ * 鍙傛暟閰嶇疆 淇℃伅鎿嶄綔澶勭悊
+ * 
+ * @author jc
+ */
+@RestController
+@RequestMapping("/system/config")
+public class SysConfigController extends BaseController
+{
+    @Autowired
+    private ISysConfigService configService;
+
+    /**
+     * 鑾峰彇鍙傛暟閰嶇疆鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('system:config:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(SysConfig config)
+    {
+        startPage();
+        List<SysConfig> list = configService.selectConfigList(config);
+        return getDataTable(list);
+    }
+
+    @Log(title = "鍙傛暟绠$悊", businessType = BusinessType.EXPORT)
+    @PreAuthorize("@ss.hasPermi('system:config:export')")
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, SysConfig config)
+    {
+        List<SysConfig> list = configService.selectConfigList(config);
+        ExcelUtil<SysConfig> util = new ExcelUtil<SysConfig>(SysConfig.class);
+        util.exportExcel(response, list, "鍙傛暟鏁版嵁");
+    }
+
+    /**
+     * 鏍规嵁鍙傛暟缂栧彿鑾峰彇璇︾粏淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('system:config:query')")
+    @GetMapping(value = "/{configId}")
+    public AjaxResult getInfo(@PathVariable Long configId)
+    {
+        return success(configService.selectConfigById(configId));
+    }
+
+    /**
+     * 鏍规嵁鍙傛暟閿悕鏌ヨ鍙傛暟鍊�
+     */
+    @GetMapping(value = "/configKey/{configKey}")
+    public AjaxResult getConfigKey(@PathVariable String configKey)
+    {
+        return success(configService.selectConfigByKey(configKey));
+    }
+
+    /**
+     * 鏂板鍙傛暟閰嶇疆
+     */
+    @PreAuthorize("@ss.hasPermi('system:config:add')")
+    @Log(title = "鍙傛暟绠$悊", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@Validated @RequestBody SysConfig config)
+    {
+        if (!configService.checkConfigKeyUnique(config))
+        {
+            return error("鏂板鍙傛暟'" + config.getConfigName() + "'澶辫触锛屽弬鏁伴敭鍚嶅凡瀛樺湪");
+        }
+        config.setCreateBy(getUsername());
+        return toAjax(configService.insertConfig(config));
+    }
+
+    /**
+     * 淇敼鍙傛暟閰嶇疆
+     */
+    @PreAuthorize("@ss.hasPermi('system:config:edit')")
+    @Log(title = "鍙傛暟绠$悊", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@Validated @RequestBody SysConfig config)
+    {
+        if (!configService.checkConfigKeyUnique(config))
+        {
+            return error("淇敼鍙傛暟'" + config.getConfigName() + "'澶辫触锛屽弬鏁伴敭鍚嶅凡瀛樺湪");
+        }
+        config.setUpdateBy(getUsername());
+        return toAjax(configService.updateConfig(config));
+    }
+
+    /**
+     * 鍒犻櫎鍙傛暟閰嶇疆
+     */
+    @PreAuthorize("@ss.hasPermi('system:config:remove')")
+    @Log(title = "鍙傛暟绠$悊", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{configIds}")
+    public AjaxResult remove(@PathVariable Long[] configIds)
+    {
+        configService.deleteConfigByIds(configIds);
+        return success();
+    }
+
+    /**
+     * 鍒锋柊鍙傛暟缂撳瓨
+     */
+    @PreAuthorize("@ss.hasPermi('system:config:remove')")
+    @Log(title = "鍙傛暟绠$悊", businessType = BusinessType.CLEAN)
+    @DeleteMapping("/refreshCache")
+    public AjaxResult refreshCache()
+    {
+        configService.resetConfigCache();
+        return success();
+    }
+}
diff --git a/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysDeptController.java b/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysDeptController.java
new file mode 100644
index 0000000..4db1604
--- /dev/null
+++ b/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysDeptController.java
@@ -0,0 +1,132 @@
+package com.jcdm.web.controller.system;
+
+import java.util.List;
+import org.apache.commons.lang3.ArrayUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.constant.UserConstants;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.core.domain.entity.SysDept;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.system.service.ISysDeptService;
+
+/**
+ * 閮ㄩ棬淇℃伅
+ * 
+ * @author jc
+ */
+@RestController
+@RequestMapping("/system/dept")
+public class SysDeptController extends BaseController
+{
+    @Autowired
+    private ISysDeptService deptService;
+
+    /**
+     * 鑾峰彇閮ㄩ棬鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('system:dept:list')")
+    @GetMapping("/list")
+    public AjaxResult list(SysDept dept)
+    {
+        List<SysDept> depts = deptService.selectDeptList(dept);
+        return success(depts);
+    }
+
+    /**
+     * 鏌ヨ閮ㄩ棬鍒楄〃锛堟帓闄よ妭鐐癸級
+     */
+    @PreAuthorize("@ss.hasPermi('system:dept:list')")
+    @GetMapping("/list/exclude/{deptId}")
+    public AjaxResult excludeChild(@PathVariable(value = "deptId", required = false) Long deptId)
+    {
+        List<SysDept> depts = deptService.selectDeptList(new SysDept());
+        depts.removeIf(d -> d.getDeptId().intValue() == deptId || ArrayUtils.contains(StringUtils.split(d.getAncestors(), ","), deptId + ""));
+        return success(depts);
+    }
+
+    /**
+     * 鏍规嵁閮ㄩ棬缂栧彿鑾峰彇璇︾粏淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('system:dept:query')")
+    @GetMapping(value = "/{deptId}")
+    public AjaxResult getInfo(@PathVariable Long deptId)
+    {
+        deptService.checkDeptDataScope(deptId);
+        return success(deptService.selectDeptById(deptId));
+    }
+
+    /**
+     * 鏂板閮ㄩ棬
+     */
+    @PreAuthorize("@ss.hasPermi('system:dept:add')")
+    @Log(title = "閮ㄩ棬绠$悊", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@Validated @RequestBody SysDept dept)
+    {
+        if (!deptService.checkDeptNameUnique(dept))
+        {
+            return error("鏂板閮ㄩ棬'" + dept.getDeptName() + "'澶辫触锛岄儴闂ㄥ悕绉板凡瀛樺湪");
+        }
+        dept.setCreateBy(getUsername());
+        return toAjax(deptService.insertDept(dept));
+    }
+
+    /**
+     * 淇敼閮ㄩ棬
+     */
+    @PreAuthorize("@ss.hasPermi('system:dept:edit')")
+    @Log(title = "閮ㄩ棬绠$悊", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@Validated @RequestBody SysDept dept)
+    {
+        Long deptId = dept.getDeptId();
+        deptService.checkDeptDataScope(deptId);
+        if (!deptService.checkDeptNameUnique(dept))
+        {
+            return error("淇敼閮ㄩ棬'" + dept.getDeptName() + "'澶辫触锛岄儴闂ㄥ悕绉板凡瀛樺湪");
+        }
+        else if (dept.getParentId().equals(deptId))
+        {
+            return error("淇敼閮ㄩ棬'" + dept.getDeptName() + "'澶辫触锛屼笂绾ч儴闂ㄤ笉鑳芥槸鑷繁");
+        }
+        else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus()) && deptService.selectNormalChildrenDeptById(deptId) > 0)
+        {
+            return error("璇ラ儴闂ㄥ寘鍚湭鍋滅敤鐨勫瓙閮ㄩ棬锛�");
+        }
+        dept.setUpdateBy(getUsername());
+        return toAjax(deptService.updateDept(dept));
+    }
+
+    /**
+     * 鍒犻櫎閮ㄩ棬
+     */
+    @PreAuthorize("@ss.hasPermi('system:dept:remove')")
+    @Log(title = "閮ㄩ棬绠$悊", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{deptId}")
+    public AjaxResult remove(@PathVariable Long deptId)
+    {
+        if (deptService.hasChildByDeptId(deptId))
+        {
+            return warn("瀛樺湪涓嬬骇閮ㄩ棬,涓嶅厑璁稿垹闄�");
+        }
+        if (deptService.checkDeptExistUser(deptId))
+        {
+            return warn("閮ㄩ棬瀛樺湪鐢ㄦ埛,涓嶅厑璁稿垹闄�");
+        }
+        deptService.checkDeptDataScope(deptId);
+        return toAjax(deptService.deleteDeptById(deptId));
+    }
+}
diff --git a/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysDictDataController.java b/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysDictDataController.java
new file mode 100644
index 0000000..8fb7cef
--- /dev/null
+++ b/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysDictDataController.java
@@ -0,0 +1,121 @@
+package com.jcdm.web.controller.system;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.core.domain.entity.SysDictData;
+import com.jcdm.common.core.page.TableDataInfo;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.common.utils.poi.ExcelUtil;
+import com.jcdm.system.service.ISysDictDataService;
+import com.jcdm.system.service.ISysDictTypeService;
+
+/**
+ * 鏁版嵁瀛楀吀淇℃伅
+ * 
+ * @author jc
+ */
+@RestController
+@RequestMapping("/system/dict/data")
+public class SysDictDataController extends BaseController
+{
+    @Autowired
+    private ISysDictDataService dictDataService;
+
+    @Autowired
+    private ISysDictTypeService dictTypeService;
+
+    @PreAuthorize("@ss.hasPermi('system:dict:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(SysDictData dictData)
+    {
+        startPage();
+        List<SysDictData> list = dictDataService.selectDictDataList(dictData);
+        return getDataTable(list);
+    }
+
+    @Log(title = "瀛楀吀鏁版嵁", businessType = BusinessType.EXPORT)
+    @PreAuthorize("@ss.hasPermi('system:dict:export')")
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, SysDictData dictData)
+    {
+        List<SysDictData> list = dictDataService.selectDictDataList(dictData);
+        ExcelUtil<SysDictData> util = new ExcelUtil<SysDictData>(SysDictData.class);
+        util.exportExcel(response, list, "瀛楀吀鏁版嵁");
+    }
+
+    /**
+     * 鏌ヨ瀛楀吀鏁版嵁璇︾粏
+     */
+    @PreAuthorize("@ss.hasPermi('system:dict:query')")
+    @GetMapping(value = "/{dictCode}")
+    public AjaxResult getInfo(@PathVariable Long dictCode)
+    {
+        return success(dictDataService.selectDictDataById(dictCode));
+    }
+
+    /**
+     * 鏍规嵁瀛楀吀绫诲瀷鏌ヨ瀛楀吀鏁版嵁淇℃伅
+     */
+    @GetMapping(value = "/type/{dictType}")
+    public AjaxResult dictType(@PathVariable String dictType)
+    {
+        List<SysDictData> data = dictTypeService.selectDictDataByType(dictType);
+        if (StringUtils.isNull(data))
+        {
+            data = new ArrayList<SysDictData>();
+        }
+        return success(data);
+    }
+
+    /**
+     * 鏂板瀛楀吀绫诲瀷
+     */
+    @PreAuthorize("@ss.hasPermi('system:dict:add')")
+    @Log(title = "瀛楀吀鏁版嵁", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@Validated @RequestBody SysDictData dict)
+    {
+        dict.setCreateBy(getUsername());
+        return toAjax(dictDataService.insertDictData(dict));
+    }
+
+    /**
+     * 淇敼淇濆瓨瀛楀吀绫诲瀷
+     */
+    @PreAuthorize("@ss.hasPermi('system:dict:edit')")
+    @Log(title = "瀛楀吀鏁版嵁", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@Validated @RequestBody SysDictData dict)
+    {
+        dict.setUpdateBy(getUsername());
+        return toAjax(dictDataService.updateDictData(dict));
+    }
+
+    /**
+     * 鍒犻櫎瀛楀吀绫诲瀷
+     */
+    @PreAuthorize("@ss.hasPermi('system:dict:remove')")
+    @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{dictCodes}")
+    public AjaxResult remove(@PathVariable Long[] dictCodes)
+    {
+        dictDataService.deleteDictDataByIds(dictCodes);
+        return success();
+    }
+}
diff --git a/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysDictTypeController.java b/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysDictTypeController.java
new file mode 100644
index 0000000..e5a35a6
--- /dev/null
+++ b/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysDictTypeController.java
@@ -0,0 +1,131 @@
+package com.jcdm.web.controller.system;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.core.domain.entity.SysDictType;
+import com.jcdm.common.core.page.TableDataInfo;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.common.utils.poi.ExcelUtil;
+import com.jcdm.system.service.ISysDictTypeService;
+
+/**
+ * 鏁版嵁瀛楀吀淇℃伅
+ * 
+ * @author jc
+ */
+@RestController
+@RequestMapping("/system/dict/type")
+public class SysDictTypeController extends BaseController
+{
+    @Autowired
+    private ISysDictTypeService dictTypeService;
+
+    @PreAuthorize("@ss.hasPermi('system:dict:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(SysDictType dictType)
+    {
+        startPage();
+        List<SysDictType> list = dictTypeService.selectDictTypeList(dictType);
+        return getDataTable(list);
+    }
+
+    @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.EXPORT)
+    @PreAuthorize("@ss.hasPermi('system:dict:export')")
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, SysDictType dictType)
+    {
+        List<SysDictType> list = dictTypeService.selectDictTypeList(dictType);
+        ExcelUtil<SysDictType> util = new ExcelUtil<SysDictType>(SysDictType.class);
+        util.exportExcel(response, list, "瀛楀吀绫诲瀷");
+    }
+
+    /**
+     * 鏌ヨ瀛楀吀绫诲瀷璇︾粏
+     */
+    @PreAuthorize("@ss.hasPermi('system:dict:query')")
+    @GetMapping(value = "/{dictId}")
+    public AjaxResult getInfo(@PathVariable Long dictId)
+    {
+        return success(dictTypeService.selectDictTypeById(dictId));
+    }
+
+    /**
+     * 鏂板瀛楀吀绫诲瀷
+     */
+    @PreAuthorize("@ss.hasPermi('system:dict:add')")
+    @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@Validated @RequestBody SysDictType dict)
+    {
+        if (!dictTypeService.checkDictTypeUnique(dict))
+        {
+            return error("鏂板瀛楀吀'" + dict.getDictName() + "'澶辫触锛屽瓧鍏哥被鍨嬪凡瀛樺湪");
+        }
+        dict.setCreateBy(getUsername());
+        return toAjax(dictTypeService.insertDictType(dict));
+    }
+
+    /**
+     * 淇敼瀛楀吀绫诲瀷
+     */
+    @PreAuthorize("@ss.hasPermi('system:dict:edit')")
+    @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@Validated @RequestBody SysDictType dict)
+    {
+        if (!dictTypeService.checkDictTypeUnique(dict))
+        {
+            return error("淇敼瀛楀吀'" + dict.getDictName() + "'澶辫触锛屽瓧鍏哥被鍨嬪凡瀛樺湪");
+        }
+        dict.setUpdateBy(getUsername());
+        return toAjax(dictTypeService.updateDictType(dict));
+    }
+
+    /**
+     * 鍒犻櫎瀛楀吀绫诲瀷
+     */
+    @PreAuthorize("@ss.hasPermi('system:dict:remove')")
+    @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{dictIds}")
+    public AjaxResult remove(@PathVariable Long[] dictIds)
+    {
+        dictTypeService.deleteDictTypeByIds(dictIds);
+        return success();
+    }
+
+    /**
+     * 鍒锋柊瀛楀吀缂撳瓨
+     */
+    @PreAuthorize("@ss.hasPermi('system:dict:remove')")
+    @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.CLEAN)
+    @DeleteMapping("/refreshCache")
+    public AjaxResult refreshCache()
+    {
+        dictTypeService.resetDictCache();
+        return success();
+    }
+
+    /**
+     * 鑾峰彇瀛楀吀閫夋嫨妗嗗垪琛�
+     */
+    @GetMapping("/optionselect")
+    public AjaxResult optionselect()
+    {
+        List<SysDictType> dictTypes = dictTypeService.selectDictTypeAll();
+        return success(dictTypes);
+    }
+}
diff --git a/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysIndexController.java b/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysIndexController.java
new file mode 100644
index 0000000..dae8f0d
--- /dev/null
+++ b/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysIndexController.java
@@ -0,0 +1,29 @@
+package com.jcdm.web.controller.system;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.config.MesConfig;
+import com.jcdm.common.utils.StringUtils;
+
+/**
+ * 棣栭〉
+ *
+ * @author jc
+ */
+@RestController
+public class SysIndexController
+{
+    /** 绯荤粺鍩虹閰嶇疆 */
+    @Autowired
+    private MesConfig mesConfig;
+
+    /**
+     * 璁块棶棣栭〉锛屾彁绀鸿
+     */
+    @RequestMapping("/")
+    public String index()
+    {
+        return StringUtils.format("娆㈣繋浣跨敤{}鍚庡彴绠$悊妗嗘灦锛屽綋鍓嶇増鏈細v{}锛岃閫氳繃鍓嶇鍦板潃璁块棶銆�", mesConfig.getName(), mesConfig.getVersion());
+    }
+}
diff --git a/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysLoginController.java b/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysLoginController.java
new file mode 100644
index 0000000..bc3a8dc
--- /dev/null
+++ b/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysLoginController.java
@@ -0,0 +1,86 @@
+package com.jcdm.web.controller.system;
+
+import java.util.List;
+import java.util.Set;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.constant.Constants;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.core.domain.entity.SysMenu;
+import com.jcdm.common.core.domain.entity.SysUser;
+import com.jcdm.common.core.domain.model.LoginBody;
+import com.jcdm.common.utils.SecurityUtils;
+import com.jcdm.framework.web.service.SysLoginService;
+import com.jcdm.framework.web.service.SysPermissionService;
+import com.jcdm.system.service.ISysMenuService;
+
+/**
+ * 鐧诲綍楠岃瘉
+ * 
+ * @author jc
+ */
+@RestController
+public class SysLoginController
+{
+    @Autowired
+    private SysLoginService loginService;
+
+    @Autowired
+    private ISysMenuService menuService;
+
+    @Autowired
+    private SysPermissionService permissionService;
+
+    /**
+     * 鐧诲綍鏂规硶
+     * 
+     * @param loginBody 鐧诲綍淇℃伅
+     * @return 缁撴灉
+     */
+    @PostMapping("/login")
+    public AjaxResult login(@RequestBody LoginBody loginBody)
+    {
+        AjaxResult ajax = AjaxResult.success();
+        // 鐢熸垚浠ょ墝
+        String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
+                loginBody.getUuid());
+        ajax.put(Constants.TOKEN, token);
+        return ajax;
+    }
+
+    /**
+     * 鑾峰彇鐢ㄦ埛淇℃伅
+     * 
+     * @return 鐢ㄦ埛淇℃伅
+     */
+    @GetMapping("getInfo")
+    public AjaxResult getInfo()
+    {
+        SysUser user = SecurityUtils.getLoginUser().getUser();
+        // 瑙掕壊闆嗗悎
+        Set<String> roles = permissionService.getRolePermission(user);
+        // 鏉冮檺闆嗗悎
+        Set<String> permissions = permissionService.getMenuPermission(user);
+        AjaxResult ajax = AjaxResult.success();
+        ajax.put("user", user);
+        ajax.put("roles", roles);
+        ajax.put("permissions", permissions);
+        return ajax;
+    }
+
+    /**
+     * 鑾峰彇璺敱淇℃伅
+     * 
+     * @return 璺敱淇℃伅
+     */
+    @GetMapping("getRouters")
+    public AjaxResult getRouters()
+    {
+        Long userId = SecurityUtils.getUserId();
+        List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
+        return AjaxResult.success(menuService.buildMenus(menus));
+    }
+}
diff --git a/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysMenuController.java b/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysMenuController.java
new file mode 100644
index 0000000..5f03ca6
--- /dev/null
+++ b/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysMenuController.java
@@ -0,0 +1,142 @@
+package com.jcdm.web.controller.system;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.constant.UserConstants;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.core.domain.entity.SysMenu;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.system.service.ISysMenuService;
+
+/**
+ * 鑿滃崟淇℃伅
+ * 
+ * @author jc
+ */
+@RestController
+@RequestMapping("/system/menu")
+public class SysMenuController extends BaseController
+{
+    @Autowired
+    private ISysMenuService menuService;
+
+    /**
+     * 鑾峰彇鑿滃崟鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('system:menu:list')")
+    @GetMapping("/list")
+    public AjaxResult list(SysMenu menu)
+    {
+        List<SysMenu> menus = menuService.selectMenuList(menu, getUserId());
+        return success(menus);
+    }
+
+    /**
+     * 鏍规嵁鑿滃崟缂栧彿鑾峰彇璇︾粏淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('system:menu:query')")
+    @GetMapping(value = "/{menuId}")
+    public AjaxResult getInfo(@PathVariable Long menuId)
+    {
+        return success(menuService.selectMenuById(menuId));
+    }
+
+    /**
+     * 鑾峰彇鑿滃崟涓嬫媺鏍戝垪琛�
+     */
+    @GetMapping("/treeselect")
+    public AjaxResult treeselect(SysMenu menu)
+    {
+        List<SysMenu> menus = menuService.selectMenuList(menu, getUserId());
+        return success(menuService.buildMenuTreeSelect(menus));
+    }
+
+    /**
+     * 鍔犺浇瀵瑰簲瑙掕壊鑿滃崟鍒楄〃鏍�
+     */
+    @GetMapping(value = "/roleMenuTreeselect/{roleId}")
+    public AjaxResult roleMenuTreeselect(@PathVariable("roleId") Long roleId)
+    {
+        List<SysMenu> menus = menuService.selectMenuList(getUserId());
+        AjaxResult ajax = AjaxResult.success();
+        ajax.put("checkedKeys", menuService.selectMenuListByRoleId(roleId));
+        ajax.put("menus", menuService.buildMenuTreeSelect(menus));
+        return ajax;
+    }
+
+    /**
+     * 鏂板鑿滃崟
+     */
+    @PreAuthorize("@ss.hasPermi('system:menu:add')")
+    @Log(title = "鑿滃崟绠$悊", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@Validated @RequestBody SysMenu menu)
+    {
+        if (!menuService.checkMenuNameUnique(menu))
+        {
+            return error("鏂板鑿滃崟'" + menu.getMenuName() + "'澶辫触锛岃彍鍗曞悕绉板凡瀛樺湪");
+        }
+        else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath()))
+        {
+            return error("鏂板鑿滃崟'" + menu.getMenuName() + "'澶辫触锛屽湴鍧�蹇呴』浠ttp(s)://寮�澶�");
+        }
+        menu.setCreateBy(getUsername());
+        return toAjax(menuService.insertMenu(menu));
+    }
+
+    /**
+     * 淇敼鑿滃崟
+     */
+    @PreAuthorize("@ss.hasPermi('system:menu:edit')")
+    @Log(title = "鑿滃崟绠$悊", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@Validated @RequestBody SysMenu menu)
+    {
+        if (!menuService.checkMenuNameUnique(menu))
+        {
+            return error("淇敼鑿滃崟'" + menu.getMenuName() + "'澶辫触锛岃彍鍗曞悕绉板凡瀛樺湪");
+        }
+        else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath()))
+        {
+            return error("淇敼鑿滃崟'" + menu.getMenuName() + "'澶辫触锛屽湴鍧�蹇呴』浠ttp(s)://寮�澶�");
+        }
+        else if (menu.getMenuId().equals(menu.getParentId()))
+        {
+            return error("淇敼鑿滃崟'" + menu.getMenuName() + "'澶辫触锛屼笂绾ц彍鍗曚笉鑳介�夋嫨鑷繁");
+        }
+        menu.setUpdateBy(getUsername());
+        return toAjax(menuService.updateMenu(menu));
+    }
+
+    /**
+     * 鍒犻櫎鑿滃崟
+     */
+    @PreAuthorize("@ss.hasPermi('system:menu:remove')")
+    @Log(title = "鑿滃崟绠$悊", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{menuId}")
+    public AjaxResult remove(@PathVariable("menuId") Long menuId)
+    {
+        if (menuService.hasChildByMenuId(menuId))
+        {
+            return warn("瀛樺湪瀛愯彍鍗�,涓嶅厑璁稿垹闄�");
+        }
+        if (menuService.checkMenuExistRole(menuId))
+        {
+            return warn("鑿滃崟宸插垎閰�,涓嶅厑璁稿垹闄�");
+        }
+        return toAjax(menuService.deleteMenuById(menuId));
+    }
+}
\ No newline at end of file
diff --git a/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysNoticeController.java b/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysNoticeController.java
new file mode 100644
index 0000000..18d8448
--- /dev/null
+++ b/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysNoticeController.java
@@ -0,0 +1,91 @@
+package com.jcdm.web.controller.system;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.core.page.TableDataInfo;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.system.domain.SysNotice;
+import com.jcdm.system.service.ISysNoticeService;
+
+/**
+ * 鍏憡 淇℃伅鎿嶄綔澶勭悊
+ * 
+ * @author jc
+ */
+@RestController
+@RequestMapping("/system/notice")
+public class SysNoticeController extends BaseController
+{
+    @Autowired
+    private ISysNoticeService noticeService;
+
+    /**
+     * 鑾峰彇閫氱煡鍏憡鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('system:notice:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(SysNotice notice)
+    {
+        startPage();
+        List<SysNotice> list = noticeService.selectNoticeList(notice);
+        return getDataTable(list);
+    }
+
+    /**
+     * 鏍规嵁閫氱煡鍏憡缂栧彿鑾峰彇璇︾粏淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('system:notice:query')")
+    @GetMapping(value = "/{noticeId}")
+    public AjaxResult getInfo(@PathVariable Long noticeId)
+    {
+        return success(noticeService.selectNoticeById(noticeId));
+    }
+
+    /**
+     * 鏂板閫氱煡鍏憡
+     */
+    @PreAuthorize("@ss.hasPermi('system:notice:add')")
+    @Log(title = "閫氱煡鍏憡", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@Validated @RequestBody SysNotice notice)
+    {
+        notice.setCreateBy(getUsername());
+        return toAjax(noticeService.insertNotice(notice));
+    }
+
+    /**
+     * 淇敼閫氱煡鍏憡
+     */
+    @PreAuthorize("@ss.hasPermi('system:notice:edit')")
+    @Log(title = "閫氱煡鍏憡", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@Validated @RequestBody SysNotice notice)
+    {
+        notice.setUpdateBy(getUsername());
+        return toAjax(noticeService.updateNotice(notice));
+    }
+
+    /**
+     * 鍒犻櫎閫氱煡鍏憡
+     */
+    @PreAuthorize("@ss.hasPermi('system:notice:remove')")
+    @Log(title = "閫氱煡鍏憡", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{noticeIds}")
+    public AjaxResult remove(@PathVariable Long[] noticeIds)
+    {
+        return toAjax(noticeService.deleteNoticeByIds(noticeIds));
+    }
+}
diff --git a/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysPostController.java b/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysPostController.java
new file mode 100644
index 0000000..f1bfb7a
--- /dev/null
+++ b/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysPostController.java
@@ -0,0 +1,129 @@
+package com.jcdm.web.controller.system;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.core.page.TableDataInfo;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.common.utils.poi.ExcelUtil;
+import com.jcdm.system.domain.SysPost;
+import com.jcdm.system.service.ISysPostService;
+
+/**
+ * 宀椾綅淇℃伅鎿嶄綔澶勭悊
+ * 
+ * @author jc
+ */
+@RestController
+@RequestMapping("/system/post")
+public class SysPostController extends BaseController
+{
+    @Autowired
+    private ISysPostService postService;
+
+    /**
+     * 鑾峰彇宀椾綅鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('system:post:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(SysPost post)
+    {
+        startPage();
+        List<SysPost> list = postService.selectPostList(post);
+        return getDataTable(list);
+    }
+    
+    @Log(title = "宀椾綅绠$悊", businessType = BusinessType.EXPORT)
+    @PreAuthorize("@ss.hasPermi('system:post:export')")
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, SysPost post)
+    {
+        List<SysPost> list = postService.selectPostList(post);
+        ExcelUtil<SysPost> util = new ExcelUtil<SysPost>(SysPost.class);
+        util.exportExcel(response, list, "宀椾綅鏁版嵁");
+    }
+
+    /**
+     * 鏍规嵁宀椾綅缂栧彿鑾峰彇璇︾粏淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('system:post:query')")
+    @GetMapping(value = "/{postId}")
+    public AjaxResult getInfo(@PathVariable Long postId)
+    {
+        return success(postService.selectPostById(postId));
+    }
+
+    /**
+     * 鏂板宀椾綅
+     */
+    @PreAuthorize("@ss.hasPermi('system:post:add')")
+    @Log(title = "宀椾綅绠$悊", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@Validated @RequestBody SysPost post)
+    {
+        if (!postService.checkPostNameUnique(post))
+        {
+            return error("鏂板宀椾綅'" + post.getPostName() + "'澶辫触锛屽矖浣嶅悕绉板凡瀛樺湪");
+        }
+        else if (!postService.checkPostCodeUnique(post))
+        {
+            return error("鏂板宀椾綅'" + post.getPostName() + "'澶辫触锛屽矖浣嶇紪鐮佸凡瀛樺湪");
+        }
+        post.setCreateBy(getUsername());
+        return toAjax(postService.insertPost(post));
+    }
+
+    /**
+     * 淇敼宀椾綅
+     */
+    @PreAuthorize("@ss.hasPermi('system:post:edit')")
+    @Log(title = "宀椾綅绠$悊", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@Validated @RequestBody SysPost post)
+    {
+        if (!postService.checkPostNameUnique(post))
+        {
+            return error("淇敼宀椾綅'" + post.getPostName() + "'澶辫触锛屽矖浣嶅悕绉板凡瀛樺湪");
+        }
+        else if (!postService.checkPostCodeUnique(post))
+        {
+            return error("淇敼宀椾綅'" + post.getPostName() + "'澶辫触锛屽矖浣嶇紪鐮佸凡瀛樺湪");
+        }
+        post.setUpdateBy(getUsername());
+        return toAjax(postService.updatePost(post));
+    }
+
+    /**
+     * 鍒犻櫎宀椾綅
+     */
+    @PreAuthorize("@ss.hasPermi('system:post:remove')")
+    @Log(title = "宀椾綅绠$悊", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{postIds}")
+    public AjaxResult remove(@PathVariable Long[] postIds)
+    {
+        return toAjax(postService.deletePostByIds(postIds));
+    }
+
+    /**
+     * 鑾峰彇宀椾綅閫夋嫨妗嗗垪琛�
+     */
+    @GetMapping("/optionselect")
+    public AjaxResult optionselect()
+    {
+        List<SysPost> posts = postService.selectPostAll();
+        return success(posts);
+    }
+}
diff --git a/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysProfileController.java b/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysProfileController.java
new file mode 100644
index 0000000..a8a60ba
--- /dev/null
+++ b/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysProfileController.java
@@ -0,0 +1,137 @@
+package com.jcdm.web.controller.system;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.config.MesConfig;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.core.domain.entity.SysUser;
+import com.jcdm.common.core.domain.model.LoginUser;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.common.utils.SecurityUtils;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.common.utils.file.FileUploadUtils;
+import com.jcdm.common.utils.file.MimeTypeUtils;
+import com.jcdm.framework.web.service.TokenService;
+import com.jcdm.system.service.ISysUserService;
+
+/**
+ * 涓汉淇℃伅 涓氬姟澶勭悊
+ * 
+ * @author jc
+ */
+@RestController
+@RequestMapping("/system/user/profile")
+public class SysProfileController extends BaseController
+{
+    @Autowired
+    private ISysUserService userService;
+
+    @Autowired
+    private TokenService tokenService;
+
+    /**
+     * 涓汉淇℃伅
+     */
+    @GetMapping
+    public AjaxResult profile()
+    {
+        LoginUser loginUser = getLoginUser();
+        SysUser user = loginUser.getUser();
+        AjaxResult ajax = AjaxResult.success(user);
+        ajax.put("roleGroup", userService.selectUserRoleGroup(loginUser.getUsername()));
+        ajax.put("postGroup", userService.selectUserPostGroup(loginUser.getUsername()));
+        return ajax;
+    }
+
+    /**
+     * 淇敼鐢ㄦ埛
+     */
+    @Log(title = "涓汉淇℃伅", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult updateProfile(@RequestBody SysUser user)
+    {
+        LoginUser loginUser = getLoginUser();
+        SysUser currentUser = loginUser.getUser();
+        currentUser.setNickName(user.getNickName());
+        currentUser.setEmail(user.getEmail());
+        currentUser.setPhonenumber(user.getPhonenumber());
+        currentUser.setSex(user.getSex());
+        if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(currentUser))
+        {
+            return error("淇敼鐢ㄦ埛'" + loginUser.getUsername() + "'澶辫触锛屾墜鏈哄彿鐮佸凡瀛樺湪");
+        }
+        if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(currentUser))
+        {
+            return error("淇敼鐢ㄦ埛'" + loginUser.getUsername() + "'澶辫触锛岄偖绠辫处鍙峰凡瀛樺湪");
+        }
+        if (userService.updateUserProfile(currentUser) > 0)
+        {
+            // 鏇存柊缂撳瓨鐢ㄦ埛淇℃伅
+            tokenService.setLoginUser(loginUser);
+            return success();
+        }
+        return error("淇敼涓汉淇℃伅寮傚父锛岃鑱旂郴绠$悊鍛�");
+    }
+
+    /**
+     * 閲嶇疆瀵嗙爜
+     */
+    @Log(title = "涓汉淇℃伅", businessType = BusinessType.UPDATE)
+    @PutMapping("/updatePwd")
+    public AjaxResult updatePwd(String oldPassword, String newPassword)
+    {
+        LoginUser loginUser = getLoginUser();
+        String userName = loginUser.getUsername();
+        String password = loginUser.getPassword();
+        if (!SecurityUtils.matchesPassword(oldPassword, password))
+        {
+            return error("淇敼瀵嗙爜澶辫触锛屾棫瀵嗙爜閿欒");
+        }
+        if (SecurityUtils.matchesPassword(newPassword, password))
+        {
+            return error("鏂板瘑鐮佷笉鑳戒笌鏃у瘑鐮佺浉鍚�");
+        }
+        newPassword = SecurityUtils.encryptPassword(newPassword);
+        if (userService.resetUserPwd(userName, newPassword) > 0)
+        {
+            // 鏇存柊缂撳瓨鐢ㄦ埛瀵嗙爜
+            loginUser.getUser().setPassword(newPassword);
+            tokenService.setLoginUser(loginUser);
+            return success();
+        }
+        return error("淇敼瀵嗙爜寮傚父锛岃鑱旂郴绠$悊鍛�");
+    }
+
+    /**
+     * 澶村儚涓婁紶
+     */
+    @Log(title = "鐢ㄦ埛澶村儚", businessType = BusinessType.UPDATE)
+    @PostMapping("/avatar")
+    public AjaxResult avatar(@RequestParam("avatarfile") MultipartFile file) throws Exception
+    {
+        if (!file.isEmpty())
+        {
+            LoginUser loginUser = getLoginUser();
+            String avatar = FileUploadUtils.upload(MesConfig.getAvatarPath(), file, MimeTypeUtils.IMAGE_EXTENSION);
+            if (userService.updateUserAvatar(loginUser.getUsername(), avatar))
+            {
+                AjaxResult ajax = AjaxResult.success();
+                ajax.put("imgUrl", avatar);
+                // 鏇存柊缂撳瓨鐢ㄦ埛澶村儚
+                loginUser.getUser().setAvatar(avatar);
+                tokenService.setLoginUser(loginUser);
+                return ajax;
+            }
+        }
+        return error("涓婁紶鍥剧墖寮傚父锛岃鑱旂郴绠$悊鍛�");
+    }
+}
diff --git a/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysRegisterController.java b/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysRegisterController.java
new file mode 100644
index 0000000..37ca41f
--- /dev/null
+++ b/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysRegisterController.java
@@ -0,0 +1,38 @@
+package com.jcdm.web.controller.system;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.core.domain.model.RegisterBody;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.framework.web.service.SysRegisterService;
+import com.jcdm.system.service.ISysConfigService;
+
+/**
+ * 娉ㄥ唽楠岃瘉
+ * 
+ * @author JC
+ */
+@RestController
+public class SysRegisterController extends BaseController
+{
+    @Autowired
+    private SysRegisterService registerService;
+
+    @Autowired
+    private ISysConfigService configService;
+
+    @PostMapping("/register")
+    public AjaxResult register(@RequestBody RegisterBody user)
+    {
+        if (!("true".equals(configService.selectConfigByKey("sys.account.registerUser"))))
+        {
+            return error("褰撳墠绯荤粺娌℃湁寮�鍚敞鍐屽姛鑳斤紒");
+        }
+        String msg = registerService.register(user);
+        return StringUtils.isEmpty(msg) ? success() : error(msg);
+    }
+}
diff --git a/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysRoleController.java b/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysRoleController.java
new file mode 100644
index 0000000..f261888
--- /dev/null
+++ b/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysRoleController.java
@@ -0,0 +1,262 @@
+package com.jcdm.web.controller.system;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.core.domain.entity.SysDept;
+import com.jcdm.common.core.domain.entity.SysRole;
+import com.jcdm.common.core.domain.entity.SysUser;
+import com.jcdm.common.core.domain.model.LoginUser;
+import com.jcdm.common.core.page.TableDataInfo;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.common.utils.poi.ExcelUtil;
+import com.jcdm.framework.web.service.SysPermissionService;
+import com.jcdm.framework.web.service.TokenService;
+import com.jcdm.system.domain.SysUserRole;
+import com.jcdm.system.service.ISysDeptService;
+import com.jcdm.system.service.ISysRoleService;
+import com.jcdm.system.service.ISysUserService;
+
+/**
+ * 瑙掕壊淇℃伅
+ * 
+ * @author jc
+ */
+@RestController
+@RequestMapping("/system/role")
+public class SysRoleController extends BaseController
+{
+    @Autowired
+    private ISysRoleService roleService;
+
+    @Autowired
+    private TokenService tokenService;
+
+    @Autowired
+    private SysPermissionService permissionService;
+
+    @Autowired
+    private ISysUserService userService;
+
+    @Autowired
+    private ISysDeptService deptService;
+
+    @PreAuthorize("@ss.hasPermi('system:role:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(SysRole role)
+    {
+        startPage();
+        List<SysRole> list = roleService.selectRoleList(role);
+        return getDataTable(list);
+    }
+
+    @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.EXPORT)
+    @PreAuthorize("@ss.hasPermi('system:role:export')")
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, SysRole role)
+    {
+        List<SysRole> list = roleService.selectRoleList(role);
+        ExcelUtil<SysRole> util = new ExcelUtil<SysRole>(SysRole.class);
+        util.exportExcel(response, list, "瑙掕壊鏁版嵁");
+    }
+
+    /**
+     * 鏍规嵁瑙掕壊缂栧彿鑾峰彇璇︾粏淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('system:role:query')")
+    @GetMapping(value = "/{roleId}")
+    public AjaxResult getInfo(@PathVariable Long roleId)
+    {
+        roleService.checkRoleDataScope(roleId);
+        return success(roleService.selectRoleById(roleId));
+    }
+
+    /**
+     * 鏂板瑙掕壊
+     */
+    @PreAuthorize("@ss.hasPermi('system:role:add')")
+    @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@Validated @RequestBody SysRole role)
+    {
+        if (!roleService.checkRoleNameUnique(role))
+        {
+            return error("鏂板瑙掕壊'" + role.getRoleName() + "'澶辫触锛岃鑹插悕绉板凡瀛樺湪");
+        }
+        else if (!roleService.checkRoleKeyUnique(role))
+        {
+            return error("鏂板瑙掕壊'" + role.getRoleName() + "'澶辫触锛岃鑹叉潈闄愬凡瀛樺湪");
+        }
+        role.setCreateBy(getUsername());
+        return toAjax(roleService.insertRole(role));
+
+    }
+
+    /**
+     * 淇敼淇濆瓨瑙掕壊
+     */
+    @PreAuthorize("@ss.hasPermi('system:role:edit')")
+    @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@Validated @RequestBody SysRole role)
+    {
+        roleService.checkRoleAllowed(role);
+        roleService.checkRoleDataScope(role.getRoleId());
+        if (!roleService.checkRoleNameUnique(role))
+        {
+            return error("淇敼瑙掕壊'" + role.getRoleName() + "'澶辫触锛岃鑹插悕绉板凡瀛樺湪");
+        }
+        else if (!roleService.checkRoleKeyUnique(role))
+        {
+            return error("淇敼瑙掕壊'" + role.getRoleName() + "'澶辫触锛岃鑹叉潈闄愬凡瀛樺湪");
+        }
+        role.setUpdateBy(getUsername());
+        
+        if (roleService.updateRole(role) > 0)
+        {
+            // 鏇存柊缂撳瓨鐢ㄦ埛鏉冮檺
+            LoginUser loginUser = getLoginUser();
+            if (StringUtils.isNotNull(loginUser.getUser()) && !loginUser.getUser().isAdmin())
+            {
+                loginUser.setPermissions(permissionService.getMenuPermission(loginUser.getUser()));
+                loginUser.setUser(userService.selectUserByUserName(loginUser.getUser().getUserName()));
+                tokenService.setLoginUser(loginUser);
+            }
+            return success();
+        }
+        return error("淇敼瑙掕壊'" + role.getRoleName() + "'澶辫触锛岃鑱旂郴绠$悊鍛�");
+    }
+
+    /**
+     * 淇敼淇濆瓨鏁版嵁鏉冮檺
+     */
+    @PreAuthorize("@ss.hasPermi('system:role:edit')")
+    @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.UPDATE)
+    @PutMapping("/dataScope")
+    public AjaxResult dataScope(@RequestBody SysRole role)
+    {
+        roleService.checkRoleAllowed(role);
+        roleService.checkRoleDataScope(role.getRoleId());
+        return toAjax(roleService.authDataScope(role));
+    }
+
+    /**
+     * 鐘舵�佷慨鏀�
+     */
+    @PreAuthorize("@ss.hasPermi('system:role:edit')")
+    @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.UPDATE)
+    @PutMapping("/changeStatus")
+    public AjaxResult changeStatus(@RequestBody SysRole role)
+    {
+        roleService.checkRoleAllowed(role);
+        roleService.checkRoleDataScope(role.getRoleId());
+        role.setUpdateBy(getUsername());
+        return toAjax(roleService.updateRoleStatus(role));
+    }
+
+    /**
+     * 鍒犻櫎瑙掕壊
+     */
+    @PreAuthorize("@ss.hasPermi('system:role:remove')")
+    @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{roleIds}")
+    public AjaxResult remove(@PathVariable Long[] roleIds)
+    {
+        return toAjax(roleService.deleteRoleByIds(roleIds));
+    }
+
+    /**
+     * 鑾峰彇瑙掕壊閫夋嫨妗嗗垪琛�
+     */
+    @PreAuthorize("@ss.hasPermi('system:role:query')")
+    @GetMapping("/optionselect")
+    public AjaxResult optionselect()
+    {
+        return success(roleService.selectRoleAll());
+    }
+
+    /**
+     * 鏌ヨ宸插垎閰嶇敤鎴疯鑹插垪琛�
+     */
+    @PreAuthorize("@ss.hasPermi('system:role:list')")
+    @GetMapping("/authUser/allocatedList")
+    public TableDataInfo allocatedList(SysUser user)
+    {
+        startPage();
+        List<SysUser> list = userService.selectAllocatedList(user);
+        return getDataTable(list);
+    }
+
+    /**
+     * 鏌ヨ鏈垎閰嶇敤鎴疯鑹插垪琛�
+     */
+    @PreAuthorize("@ss.hasPermi('system:role:list')")
+    @GetMapping("/authUser/unallocatedList")
+    public TableDataInfo unallocatedList(SysUser user)
+    {
+        startPage();
+        List<SysUser> list = userService.selectUnallocatedList(user);
+        return getDataTable(list);
+    }
+
+    /**
+     * 鍙栨秷鎺堟潈鐢ㄦ埛
+     */
+    @PreAuthorize("@ss.hasPermi('system:role:edit')")
+    @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.GRANT)
+    @PutMapping("/authUser/cancel")
+    public AjaxResult cancelAuthUser(@RequestBody SysUserRole userRole)
+    {
+        return toAjax(roleService.deleteAuthUser(userRole));
+    }
+
+    /**
+     * 鎵归噺鍙栨秷鎺堟潈鐢ㄦ埛
+     */
+    @PreAuthorize("@ss.hasPermi('system:role:edit')")
+    @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.GRANT)
+    @PutMapping("/authUser/cancelAll")
+    public AjaxResult cancelAuthUserAll(Long roleId, Long[] userIds)
+    {
+        return toAjax(roleService.deleteAuthUsers(roleId, userIds));
+    }
+
+    /**
+     * 鎵归噺閫夋嫨鐢ㄦ埛鎺堟潈
+     */
+    @PreAuthorize("@ss.hasPermi('system:role:edit')")
+    @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.GRANT)
+    @PutMapping("/authUser/selectAll")
+    public AjaxResult selectAuthUserAll(Long roleId, Long[] userIds)
+    {
+        roleService.checkRoleDataScope(roleId);
+        return toAjax(roleService.insertAuthUsers(roleId, userIds));
+    }
+
+    /**
+     * 鑾峰彇瀵瑰簲瑙掕壊閮ㄩ棬鏍戝垪琛�
+     */
+    @PreAuthorize("@ss.hasPermi('system:role:query')")
+    @GetMapping(value = "/deptTree/{roleId}")
+    public AjaxResult deptTree(@PathVariable("roleId") Long roleId)
+    {
+        AjaxResult ajax = AjaxResult.success();
+        ajax.put("checkedKeys", deptService.selectDeptListByRoleId(roleId));
+        ajax.put("depts", deptService.selectDeptTreeList(new SysDept()));
+        return ajax;
+    }
+}
diff --git a/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysUserController.java b/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysUserController.java
new file mode 100644
index 0000000..3cb46bc
--- /dev/null
+++ b/jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysUserController.java
@@ -0,0 +1,251 @@
+package com.jcdm.web.controller.system;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.lang3.ArrayUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.core.domain.entity.SysDept;
+import com.jcdm.common.core.domain.entity.SysRole;
+import com.jcdm.common.core.domain.entity.SysUser;
+import com.jcdm.common.core.page.TableDataInfo;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.common.utils.SecurityUtils;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.common.utils.poi.ExcelUtil;
+import com.jcdm.system.service.ISysDeptService;
+import com.jcdm.system.service.ISysPostService;
+import com.jcdm.system.service.ISysRoleService;
+import com.jcdm.system.service.ISysUserService;
+
+/**
+ * 鐢ㄦ埛淇℃伅
+ * 
+ * @author jc
+ */
+@RestController
+@RequestMapping("/system/user")
+public class SysUserController extends BaseController
+{
+    @Autowired
+    private ISysUserService userService;
+
+    @Autowired
+    private ISysRoleService roleService;
+
+    @Autowired
+    private ISysDeptService deptService;
+
+    @Autowired
+    private ISysPostService postService;
+
+    /**
+     * 鑾峰彇鐢ㄦ埛鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('system:user:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(SysUser user)
+    {
+        startPage();
+        List<SysUser> list = userService.selectUserList(user);
+        return getDataTable(list);
+    }
+
+    @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.EXPORT)
+    @PreAuthorize("@ss.hasPermi('system:user:export')")
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, SysUser user)
+    {
+        List<SysUser> list = userService.selectUserList(user);
+        ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
+        util.exportExcel(response, list, "鐢ㄦ埛鏁版嵁");
+    }
+
+    @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.IMPORT)
+    @PreAuthorize("@ss.hasPermi('system:user:import')")
+    @PostMapping("/importData")
+    public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception
+    {
+        ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
+        List<SysUser> userList = util.importExcel(file.getInputStream());
+        String operName = getUsername();
+        String message = userService.importUser(userList, updateSupport, operName);
+        return success(message);
+    }
+
+    @PostMapping("/importTemplate")
+    public void importTemplate(HttpServletResponse response)
+    {
+        ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
+        util.importTemplateExcel(response, "鐢ㄦ埛鏁版嵁");
+    }
+
+    /**
+     * 鏍规嵁鐢ㄦ埛缂栧彿鑾峰彇璇︾粏淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('system:user:query')")
+    @GetMapping(value = { "/", "/{userId}" })
+    public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId)
+    {
+        userService.checkUserDataScope(userId);
+        AjaxResult ajax = AjaxResult.success();
+        List<SysRole> roles = roleService.selectRoleAll();
+        ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
+        ajax.put("posts", postService.selectPostAll());
+        if (StringUtils.isNotNull(userId))
+        {
+            SysUser sysUser = userService.selectUserById(userId);
+            ajax.put(AjaxResult.DATA_TAG, sysUser);
+            ajax.put("postIds", postService.selectPostListByUserId(userId));
+            ajax.put("roleIds", sysUser.getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList()));
+        }
+        return ajax;
+    }
+
+    /**
+     * 鏂板鐢ㄦ埛
+     */
+    @PreAuthorize("@ss.hasPermi('system:user:add')")
+    @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@Validated @RequestBody SysUser user)
+    {
+        if (!userService.checkUserNameUnique(user))
+        {
+            return error("鏂板鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛岀櫥褰曡处鍙峰凡瀛樺湪");
+        }
+        else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user))
+        {
+            return error("鏂板鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛屾墜鏈哄彿鐮佸凡瀛樺湪");
+        }
+        else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user))
+        {
+            return error("鏂板鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛岄偖绠辫处鍙峰凡瀛樺湪");
+        }
+        user.setCreateBy(getUsername());
+        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
+        return toAjax(userService.insertUser(user));
+    }
+
+    /**
+     * 淇敼鐢ㄦ埛
+     */
+    @PreAuthorize("@ss.hasPermi('system:user:edit')")
+    @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@Validated @RequestBody SysUser user)
+    {
+        userService.checkUserAllowed(user);
+        userService.checkUserDataScope(user.getUserId());
+        if (!userService.checkUserNameUnique(user))
+        {
+            return error("淇敼鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛岀櫥褰曡处鍙峰凡瀛樺湪");
+        }
+        else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user))
+        {
+            return error("淇敼鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛屾墜鏈哄彿鐮佸凡瀛樺湪");
+        }
+        else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user))
+        {
+            return error("淇敼鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛岄偖绠辫处鍙峰凡瀛樺湪");
+        }
+        user.setUpdateBy(getUsername());
+        return toAjax(userService.updateUser(user));
+    }
+
+    /**
+     * 鍒犻櫎鐢ㄦ埛
+     */
+    @PreAuthorize("@ss.hasPermi('system:user:remove')")
+    @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{userIds}")
+    public AjaxResult remove(@PathVariable Long[] userIds)
+    {
+        if (ArrayUtils.contains(userIds, getUserId()))
+        {
+            return error("褰撳墠鐢ㄦ埛涓嶈兘鍒犻櫎");
+        }
+        return toAjax(userService.deleteUserByIds(userIds));
+    }
+
+    /**
+     * 閲嶇疆瀵嗙爜
+     */
+    @PreAuthorize("@ss.hasPermi('system:user:resetPwd')")
+    @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.UPDATE)
+    @PutMapping("/resetPwd")
+    public AjaxResult resetPwd(@RequestBody SysUser user)
+    {
+        userService.checkUserAllowed(user);
+        userService.checkUserDataScope(user.getUserId());
+        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
+        user.setUpdateBy(getUsername());
+        return toAjax(userService.resetPwd(user));
+    }
+
+    /**
+     * 鐘舵�佷慨鏀�
+     */
+    @PreAuthorize("@ss.hasPermi('system:user:edit')")
+    @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.UPDATE)
+    @PutMapping("/changeStatus")
+    public AjaxResult changeStatus(@RequestBody SysUser user)
+    {
+        userService.checkUserAllowed(user);
+        userService.checkUserDataScope(user.getUserId());
+        user.setUpdateBy(getUsername());
+        return toAjax(userService.updateUserStatus(user));
+    }
+
+    /**
+     * 鏍规嵁鐢ㄦ埛缂栧彿鑾峰彇鎺堟潈瑙掕壊
+     */
+    @PreAuthorize("@ss.hasPermi('system:user:query')")
+    @GetMapping("/authRole/{userId}")
+    public AjaxResult authRole(@PathVariable("userId") Long userId)
+    {
+        AjaxResult ajax = AjaxResult.success();
+        SysUser user = userService.selectUserById(userId);
+        List<SysRole> roles = roleService.selectRolesByUserId(userId);
+        ajax.put("user", user);
+        ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
+        return ajax;
+    }
+
+    /**
+     * 鐢ㄦ埛鎺堟潈瑙掕壊
+     */
+    @PreAuthorize("@ss.hasPermi('system:user:edit')")
+    @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.GRANT)
+    @PutMapping("/authRole")
+    public AjaxResult insertAuthRole(Long userId, Long[] roleIds)
+    {
+        userService.checkUserDataScope(userId);
+        userService.insertUserAuth(userId, roleIds);
+        return success();
+    }
+
+    /**
+     * 鑾峰彇閮ㄩ棬鏍戝垪琛�
+     */
+    @PreAuthorize("@ss.hasPermi('system:user:list')")
+    @GetMapping("/deptTree")
+    public AjaxResult deptTree(SysDept dept)
+    {
+        return success(deptService.selectDeptTreeList(dept));
+    }
+}
diff --git a/jcdm-admin/src/main/java/com/jcdm/web/controller/tool/TestController.java b/jcdm-admin/src/main/java/com/jcdm/web/controller/tool/TestController.java
new file mode 100644
index 0000000..e14653a
--- /dev/null
+++ b/jcdm-admin/src/main/java/com/jcdm/web/controller/tool/TestController.java
@@ -0,0 +1,183 @@
+package com.jcdm.web.controller.tool;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.R;
+import com.jcdm.common.utils.StringUtils;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import io.swagger.annotations.ApiOperation;
+
+/**
+ * swagger 鐢ㄦ埛娴嬭瘯鏂规硶
+ * 
+ * @author jc
+ */
+@Api("鐢ㄦ埛淇℃伅绠$悊")
+@RestController
+@RequestMapping("/test/user")
+public class TestController extends BaseController
+{
+    private final static Map<Integer, UserEntity> users = new LinkedHashMap<Integer, UserEntity>();
+    {
+        users.put(1, new UserEntity(1, "admin", "admin123", "15888888888"));
+        users.put(2, new UserEntity(2, "ry", "admin123", "15666666666"));
+    }
+
+    @ApiOperation("鑾峰彇鐢ㄦ埛鍒楄〃")
+    @GetMapping("/list")
+    public R<List<UserEntity>> userList()
+    {
+        List<UserEntity> userList = new ArrayList<UserEntity>(users.values());
+        return R.ok(userList);
+    }
+
+    @ApiOperation("鑾峰彇鐢ㄦ埛璇︾粏")
+    @ApiImplicitParam(name = "userId", value = "鐢ㄦ埛ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class)
+    @GetMapping("/{userId}")
+    public R<UserEntity> getUser(@PathVariable Integer userId)
+    {
+        if (!users.isEmpty() && users.containsKey(userId))
+        {
+            return R.ok(users.get(userId));
+        }
+        else
+        {
+            return R.fail("鐢ㄦ埛涓嶅瓨鍦�");
+        }
+    }
+
+    @ApiOperation("鏂板鐢ㄦ埛")
+    @ApiImplicitParams({
+        @ApiImplicitParam(name = "userId", value = "鐢ㄦ埛id", dataType = "Integer", dataTypeClass = Integer.class),
+        @ApiImplicitParam(name = "username", value = "鐢ㄦ埛鍚嶇О", dataType = "String", dataTypeClass = String.class),
+        @ApiImplicitParam(name = "password", value = "鐢ㄦ埛瀵嗙爜", dataType = "String", dataTypeClass = String.class),
+        @ApiImplicitParam(name = "mobile", value = "鐢ㄦ埛鎵嬫満", dataType = "String", dataTypeClass = String.class)
+    })
+    @PostMapping("/save")
+    public R<String> save(UserEntity user)
+    {
+        if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
+        {
+            return R.fail("鐢ㄦ埛ID涓嶈兘涓虹┖");
+        }
+        users.put(user.getUserId(), user);
+        return R.ok();
+    }
+
+    @ApiOperation("鏇存柊鐢ㄦ埛")
+    @PutMapping("/update")
+    public R<String> update(@RequestBody UserEntity user)
+    {
+        if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
+        {
+            return R.fail("鐢ㄦ埛ID涓嶈兘涓虹┖");
+        }
+        if (users.isEmpty() || !users.containsKey(user.getUserId()))
+        {
+            return R.fail("鐢ㄦ埛涓嶅瓨鍦�");
+        }
+        users.remove(user.getUserId());
+        users.put(user.getUserId(), user);
+        return R.ok();
+    }
+
+    @ApiOperation("鍒犻櫎鐢ㄦ埛淇℃伅")
+    @ApiImplicitParam(name = "userId", value = "鐢ㄦ埛ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class)
+    @DeleteMapping("/{userId}")
+    public R<String> delete(@PathVariable Integer userId)
+    {
+        if (!users.isEmpty() && users.containsKey(userId))
+        {
+            users.remove(userId);
+            return R.ok();
+        }
+        else
+        {
+            return R.fail("鐢ㄦ埛涓嶅瓨鍦�");
+        }
+    }
+}
+
+@ApiModel(value = "UserEntity", description = "鐢ㄦ埛瀹炰綋")
+class UserEntity
+{
+    @ApiModelProperty("鐢ㄦ埛ID")
+    private Integer userId;
+
+    @ApiModelProperty("鐢ㄦ埛鍚嶇О")
+    private String username;
+
+    @ApiModelProperty("鐢ㄦ埛瀵嗙爜")
+    private String password;
+
+    @ApiModelProperty("鐢ㄦ埛鎵嬫満")
+    private String mobile;
+
+    public UserEntity()
+    {
+
+    }
+
+    public UserEntity(Integer userId, String username, String password, String mobile)
+    {
+        this.userId = userId;
+        this.username = username;
+        this.password = password;
+        this.mobile = mobile;
+    }
+
+    public Integer getUserId()
+    {
+        return userId;
+    }
+
+    public void setUserId(Integer userId)
+    {
+        this.userId = userId;
+    }
+
+    public String getUsername()
+    {
+        return username;
+    }
+
+    public void setUsername(String username)
+    {
+        this.username = username;
+    }
+
+    public String getPassword()
+    {
+        return password;
+    }
+
+    public void setPassword(String password)
+    {
+        this.password = password;
+    }
+
+    public String getMobile()
+    {
+        return mobile;
+    }
+
+    public void setMobile(String mobile)
+    {
+        this.mobile = mobile;
+    }
+}
diff --git a/jcdm-admin/src/main/java/com/jcdm/web/core/config/SwaggerConfig.java b/jcdm-admin/src/main/java/com/jcdm/web/core/config/SwaggerConfig.java
new file mode 100644
index 0000000..5d1c389
--- /dev/null
+++ b/jcdm-admin/src/main/java/com/jcdm/web/core/config/SwaggerConfig.java
@@ -0,0 +1,125 @@
+package com.jcdm.web.core.config;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import com.jcdm.common.config.MesConfig;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.models.auth.In;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.service.ApiKey;
+import springfox.documentation.service.AuthorizationScope;
+import springfox.documentation.service.Contact;
+import springfox.documentation.service.SecurityReference;
+import springfox.documentation.service.SecurityScheme;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spi.service.contexts.SecurityContext;
+import springfox.documentation.spring.web.plugins.Docket;
+
+/**
+ * Swagger2鐨勬帴鍙i厤缃�
+ * 
+ * @author jc
+ */
+@Configuration
+public class SwaggerConfig
+{
+    /** 绯荤粺鍩虹閰嶇疆 */
+    @Autowired
+    private MesConfig mesConfig;
+
+    /** 鏄惁寮�鍚痵wagger */
+    @Value("${swagger.enabled}")
+    private boolean enabled;
+
+    /** 璁剧疆璇锋眰鐨勭粺涓�鍓嶇紑 */
+    @Value("${swagger.pathMapping}")
+    private String pathMapping;
+
+    /**
+     * 鍒涘缓API
+     */
+    @Bean
+    public Docket createRestApi()
+    {
+        return new Docket(DocumentationType.OAS_30)
+                // 鏄惁鍚敤Swagger
+                .enable(enabled)
+                // 鐢ㄦ潵鍒涘缓璇PI鐨勫熀鏈俊鎭紝灞曠ず鍦ㄦ枃妗g殑椤甸潰涓紙鑷畾涔夊睍绀虹殑淇℃伅锛�
+                .apiInfo(apiInfo())
+                // 璁剧疆鍝簺鎺ュ彛鏆撮湶缁橲wagger灞曠ず
+                .select()
+                // 鎵弿鎵�鏈夋湁娉ㄨВ鐨刟pi锛岀敤杩欑鏂瑰紡鏇寸伒娲�
+                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
+                // 鎵弿鎸囧畾鍖呬腑鐨剆wagger娉ㄨВ
+                // .apis(RequestHandlerSelectors.basePackage("com.jcdm.project.tool.swagger"))
+                // 鎵弿鎵�鏈� .apis(RequestHandlerSelectors.any())
+                .paths(PathSelectors.any())
+                .build()
+                /* 璁剧疆瀹夊叏妯″紡锛宻wagger鍙互璁剧疆璁块棶token */
+                .securitySchemes(securitySchemes())
+                .securityContexts(securityContexts())
+                .pathMapping(pathMapping);
+    }
+
+    /**
+     * 瀹夊叏妯″紡锛岃繖閲屾寚瀹歵oken閫氳繃Authorization澶磋姹傚ご浼犻��
+     */
+    private List<SecurityScheme> securitySchemes()
+    {
+        List<SecurityScheme> apiKeyList = new ArrayList<SecurityScheme>();
+        apiKeyList.add(new ApiKey("Authorization", "Authorization", In.HEADER.toValue()));
+        return apiKeyList;
+    }
+
+    /**
+     * 瀹夊叏涓婁笅鏂�
+     */
+    private List<SecurityContext> securityContexts()
+    {
+        List<SecurityContext> securityContexts = new ArrayList<>();
+        securityContexts.add(
+                SecurityContext.builder()
+                        .securityReferences(defaultAuth())
+                        .operationSelector(o -> o.requestMappingPattern().matches("/.*"))
+                        .build());
+        return securityContexts;
+    }
+
+    /**
+     * 榛樿鐨勫畨鍏ㄤ笂寮曠敤
+     */
+    private List<SecurityReference> defaultAuth()
+    {
+        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
+        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
+        authorizationScopes[0] = authorizationScope;
+        List<SecurityReference> securityReferences = new ArrayList<>();
+        securityReferences.add(new SecurityReference("Authorization", authorizationScopes));
+        return securityReferences;
+    }
+
+    /**
+     * 娣诲姞鎽樿淇℃伅
+     */
+    private ApiInfo apiInfo()
+    {
+        // 鐢ˋpiInfoBuilder杩涜瀹氬埗
+        return new ApiInfoBuilder()
+                // 璁剧疆鏍囬
+                .title("鏍囬锛氭睙瀹窶ES绠$悊绯荤粺_鎺ュ彛鏂囨。")
+                // 鎻忚堪
+                .description("鎻忚堪锛氱敤浜庡伐鍘傜敓浜х幇鍦虹鐞�")
+                // 浣滆�呬俊鎭�
+                .contact(new Contact(mesConfig.getName(), null, null))
+                // 鐗堟湰
+                .version("鐗堟湰鍙�:" + mesConfig.getVersion())
+                .build();
+    }
+}
diff --git a/jcdm-admin/src/main/resources/META-INF/spring-devtools.properties b/jcdm-admin/src/main/resources/META-INF/spring-devtools.properties
new file mode 100644
index 0000000..2b23f85
--- /dev/null
+++ b/jcdm-admin/src/main/resources/META-INF/spring-devtools.properties
@@ -0,0 +1 @@
+restart.include.json=/com.alibaba.fastjson.*.jar
\ No newline at end of file
diff --git a/jcdm-admin/src/main/resources/application-druid.yml b/jcdm-admin/src/main/resources/application-druid.yml
new file mode 100644
index 0000000..a68ced9
--- /dev/null
+++ b/jcdm-admin/src/main/resources/application-druid.yml
@@ -0,0 +1,72 @@
+# 鏁版嵁婧愰厤缃�
+spring:
+#    datasource:
+#        type: com.alibaba.druid.pool.DruidDataSource
+#        driverClassName: com.mysql.cj.jdbc.Driver
+#        druid:
+#            # 涓诲簱鏁版嵁婧�
+#            master:
+#                url: jdbc:mysql://192.168.0.189:3306/jcdm-mes-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+#                username: root
+#                password: root
+    # 鏁版嵁婧愰厤缃�
+    datasource:
+        type: com.alibaba.druid.pool.DruidDataSource
+        driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
+        druid:
+            # 涓诲簱鏁版嵁婧�
+            master:
+                url: jdbc:sqlserver://192.168.0.189:1433;DataBaseName=jcdm-mes
+                username: sa
+                password: JCDM@2023
+            # 浠庡簱鏁版嵁婧�
+            slave:
+                # 浠庢暟鎹簮寮�鍏�/榛樿鍏抽棴
+                enabled: false
+                url:
+                username:
+                password:
+            # 鍒濆杩炴帴鏁�
+            initialSize: 5
+            # 鏈�灏忚繛鎺ユ睜鏁伴噺
+            minIdle: 10
+            # 鏈�澶ц繛鎺ユ睜鏁伴噺
+            maxActive: 20
+            # 閰嶇疆鑾峰彇杩炴帴绛夊緟瓒呮椂鐨勬椂闂�
+            maxWait: 60000
+            # 閰嶇疆杩炴帴瓒呮椂鏃堕棿
+            connectTimeout: 30000
+            # 閰嶇疆缃戠粶瓒呮椂鏃堕棿
+            socketTimeout: 60000
+            # 閰嶇疆闂撮殧澶氫箙鎵嶈繘琛屼竴娆℃娴嬶紝妫�娴嬮渶瑕佸叧闂殑绌洪棽杩炴帴锛屽崟浣嶆槸姣
+            timeBetweenEvictionRunsMillis: 60000
+            # 閰嶇疆涓�涓繛鎺ュ湪姹犱腑鏈�灏忕敓瀛樼殑鏃堕棿锛屽崟浣嶆槸姣
+            minEvictableIdleTimeMillis: 300000
+            # 閰嶇疆涓�涓繛鎺ュ湪姹犱腑鏈�澶х敓瀛樼殑鏃堕棿锛屽崟浣嶆槸姣
+            maxEvictableIdleTimeMillis: 900000
+            # 閰嶇疆妫�娴嬭繛鎺ユ槸鍚︽湁鏁�
+#            validationQuery: SELECT 1 FROM DUAL
+            validationQuery: SELECT 1
+            testWhileIdle: true
+            testOnBorrow: false
+            testOnReturn: false
+            webStatFilter:
+                enabled: true
+            statViewServlet:
+                enabled: true
+                # 璁剧疆鐧藉悕鍗曪紝涓嶅~鍒欏厑璁告墍鏈夎闂�
+                allow:
+                url-pattern: /druid/*
+                # 鎺у埗鍙扮鐞嗙敤鎴峰悕鍜屽瘑鐮�
+                login-username: jcdm
+                login-password: 123456
+            filter:
+                stat:
+                    enabled: true
+                    # 鎱QL璁板綍
+                    log-slow-sql: true
+                    slow-sql-millis: 1000
+                    merge-sql: true
+                wall:
+                    config:
+                        multi-statement-allow: true
\ No newline at end of file
diff --git a/jcdm-admin/src/main/resources/application.yml b/jcdm-admin/src/main/resources/application.yml
new file mode 100644
index 0000000..f470bcc
--- /dev/null
+++ b/jcdm-admin/src/main/resources/application.yml
@@ -0,0 +1,132 @@
+# 椤圭洰鐩稿叧閰嶇疆
+ruoyi:
+  # 鍚嶇О
+  name: RuoYi
+  # 鐗堟湰
+  version: 3.8.6
+  # 鐗堟潈骞翠唤
+  copyrightYear: 2023
+  # 瀹炰緥婕旂ず寮�鍏�
+  demoEnabled: true
+  # 鏂囦欢璺緞 绀轰緥锛� Windows閰嶇疆D:/jcdm/uploadPath锛孡inux閰嶇疆 /home/jcdm/uploadPath锛�
+  profile: D:/mes/uploadPath
+  # 鑾峰彇ip鍦板潃寮�鍏�
+  addressEnabled: false
+  # 楠岃瘉鐮佺被鍨� math 鏁板瓧璁$畻 char 瀛楃楠岃瘉
+  captchaType: math
+
+# 寮�鍙戠幆澧冮厤缃�
+server:
+  # 鏈嶅姟鍣ㄧ殑HTTP绔彛锛岄粯璁や负8080
+  port: 8080
+  servlet:
+    # 搴旂敤鐨勮闂矾寰�
+    context-path: /
+  tomcat:
+    # tomcat鐨刄RI缂栫爜
+    uri-encoding: UTF-8
+    # 杩炴帴鏁版弧鍚庣殑鎺掗槦鏁帮紝榛樿涓�100
+    accept-count: 1000
+    threads:
+      # tomcat鏈�澶х嚎绋嬫暟锛岄粯璁や负200
+      max: 800
+      # Tomcat鍚姩鍒濆鍖栫殑绾跨▼鏁帮紝榛樿鍊�10
+      min-spare: 100
+
+# 鏃ュ織閰嶇疆
+logging:
+  level:
+    com.jcdm: debug
+    org.springframework: warn
+
+# 鐢ㄦ埛閰嶇疆
+user:
+  password:
+    # 瀵嗙爜鏈�澶ч敊璇鏁�
+    maxRetryCount: 5
+    # 瀵嗙爜閿佸畾鏃堕棿锛堥粯璁�10鍒嗛挓锛�
+    lockTime: 10
+
+# Spring閰嶇疆
+spring:
+  # 璧勬簮淇℃伅
+  messages:
+    # 鍥介檯鍖栬祫婧愭枃浠惰矾寰�
+    basename: i18n/messages
+  profiles:
+    active: druid
+  # 鏂囦欢涓婁紶
+  servlet:
+    multipart:
+      # 鍗曚釜鏂囦欢澶у皬
+      max-file-size: 10MB
+      # 璁剧疆鎬讳笂浼犵殑鏂囦欢澶у皬
+      max-request-size: 20MB
+  # 鏈嶅姟妯″潡
+  devtools:
+    restart:
+      # 鐑儴缃插紑鍏�
+      enabled: true
+  # redis 閰嶇疆
+#  redis:
+#    # 鍦板潃
+#    host: localhost
+#    # 绔彛锛岄粯璁や负6379
+#    port: 6379
+#    # 鏁版嵁搴撶储寮�
+#    database: 0
+#    # 瀵嗙爜
+#    password:
+#    # 杩炴帴瓒呮椂鏃堕棿
+#    timeout: 10s
+#    lettuce:
+#      pool:
+#        # 杩炴帴姹犱腑鐨勬渶灏忕┖闂茶繛鎺�
+#        min-idle: 0
+#        # 杩炴帴姹犱腑鐨勬渶澶х┖闂茶繛鎺�
+#        max-idle: 8
+#        # 杩炴帴姹犵殑鏈�澶ф暟鎹簱杩炴帴鏁�
+#        max-active: 8
+#        # #杩炴帴姹犳渶澶ч樆濉炵瓑寰呮椂闂达紙浣跨敤璐熷�艰〃绀烘病鏈夐檺鍒讹級
+#        max-wait: -1ms
+
+# token閰嶇疆
+token:
+  # 浠ょ墝鑷畾涔夋爣璇�
+  header: Authorization
+  # 浠ょ墝瀵嗛挜
+  secret: abcdefghijklmnopqrstuvwxyz
+  # 浠ょ墝鏈夋晥鏈燂紙榛樿30鍒嗛挓锛�
+  expireTime: 30
+
+# MyBatis閰嶇疆
+mybatis:
+  # 鎼滅储鎸囧畾鍖呭埆鍚�
+  typeAliasesPackage: com.jcdm.**.domain
+  # 閰嶇疆mapper鐨勬壂鎻忥紝鎵惧埌鎵�鏈夌殑mapper.xml鏄犲皠鏂囦欢
+  mapperLocations: classpath*:mapper/**/*Mapper.xml
+  # 鍔犺浇鍏ㄥ眬鐨勯厤缃枃浠�
+  configLocation: classpath:mybatis/mybatis-config.xml
+
+# PageHelper鍒嗛〉鎻掍欢
+pagehelper:
+#  helperDialect: mysql
+  supportMethodsArguments: true
+  params: count=countSql
+  autoRuntimeDialect: true
+
+# Swagger閰嶇疆
+swagger:
+  # 鏄惁寮�鍚痵wagger
+  enabled: true
+  # 璇锋眰鍓嶇紑
+  pathMapping: /dev-api
+
+# 闃叉XSS鏀诲嚮
+xss:
+  # 杩囨护寮�鍏�
+  enabled: true
+  # 鎺掗櫎閾炬帴锛堝涓敤閫楀彿鍒嗛殧锛�
+  excludes: /system/notice
+  # 鍖归厤閾炬帴
+  urlPatterns: /system/*,/monitor/*,/tool/*
diff --git a/jcdm-admin/src/main/resources/banner.txt b/jcdm-admin/src/main/resources/banner.txt
new file mode 100644
index 0000000..0931cb8
--- /dev/null
+++ b/jcdm-admin/src/main/resources/banner.txt
@@ -0,0 +1,24 @@
+Application Version: ${ruoyi.version}
+Spring Boot Version: ${spring-boot.version}
+////////////////////////////////////////////////////////////////////
+//                          _ooOoo_                               //
+//                         o8888888o                              //
+//                         88" . "88                              //
+//                         (| ^_^ |)                              //
+//                         O\  =  /O                              //
+//                      ____/`---'\____                           //
+//                    .'  \\|     |//  `.                         //
+//                   /  \\|||  :  |||//  \                        //
+//                  /  _||||| -:- |||||-  \                       //
+//                  |   | \\\  -  /// |   |                       //
+//                  | \_|  ''\---/''  |   |                       //
+//                  \  .-\__  `-`  ___/-. /                       //
+//                ___`. .'  /--.--\  `. . ___                     //
+//              ."" '<  `.___\_<|>_/___.'  >'"".                  //
+//            | | :  `- \`.;`\ _ /`;.`/ - ` : | |                 //
+//            \  \ `-.   \_ __\ /__ _/   .-` /  /                 //
+//      ========`-.____`-.___\_____/___.-`____.-'========         //
+//                           `=---='                              //
+//      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^        //
+//             浣涚淇濅綉       姘镐笉瀹曟満      姘告棤BUG               //
+////////////////////////////////////////////////////////////////////
\ No newline at end of file
diff --git a/jcdm-admin/src/main/resources/i18n/messages.properties b/jcdm-admin/src/main/resources/i18n/messages.properties
new file mode 100644
index 0000000..93de005
--- /dev/null
+++ b/jcdm-admin/src/main/resources/i18n/messages.properties
@@ -0,0 +1,38 @@
+#閿欒娑堟伅
+not.null=* 蹇呴』濉啓
+user.jcaptcha.error=楠岃瘉鐮侀敊璇�
+user.jcaptcha.expire=楠岃瘉鐮佸凡澶辨晥
+user.not.exists=鐢ㄦ埛涓嶅瓨鍦�/瀵嗙爜閿欒
+user.password.not.match=鐢ㄦ埛涓嶅瓨鍦�/瀵嗙爜閿欒
+user.password.retry.limit.count=瀵嗙爜杈撳叆閿欒{0}娆�
+user.password.retry.limit.exceed=瀵嗙爜杈撳叆閿欒{0}娆★紝甯愭埛閿佸畾{1}鍒嗛挓
+user.password.delete=瀵逛笉璧凤紝鎮ㄧ殑璐﹀彿宸茶鍒犻櫎
+user.blocked=鐢ㄦ埛宸插皝绂侊紝璇疯仈绯荤鐞嗗憳
+role.blocked=瑙掕壊宸插皝绂侊紝璇疯仈绯荤鐞嗗憳
+login.blocked=寰堥仐鎲撅紝璁块棶IP宸茶鍒楀叆绯荤粺榛戝悕鍗�
+user.logout.success=閫�鍑烘垚鍔�
+
+length.not.valid=闀垮害蹇呴』鍦▄min}鍒皗max}涓瓧绗︿箣闂�
+
+user.username.not.valid=* 2鍒�20涓眽瀛椼�佸瓧姣嶃�佹暟瀛楁垨涓嬪垝绾跨粍鎴愶紝涓斿繀椤讳互闈炴暟瀛楀紑澶�
+user.password.not.valid=* 5-50涓瓧绗�
+ 
+user.email.not.valid=閭鏍煎紡閿欒
+user.mobile.phone.number.not.valid=鎵嬫満鍙锋牸寮忛敊璇�
+user.login.success=鐧诲綍鎴愬姛
+user.register.success=娉ㄥ唽鎴愬姛
+user.notfound=璇烽噸鏂扮櫥褰�
+user.forcelogout=绠$悊鍛樺己鍒堕��鍑猴紝璇烽噸鏂扮櫥褰�
+user.unknown.error=鏈煡閿欒锛岃閲嶆柊鐧诲綍
+
+##鏂囦欢涓婁紶娑堟伅
+upload.exceed.maxSize=涓婁紶鐨勬枃浠跺ぇ灏忚秴鍑洪檺鍒剁殑鏂囦欢澶у皬锛�<br/>鍏佽鐨勬枃浠舵渶澶уぇ灏忔槸锛歿0}MB锛�
+upload.filename.exceed.length=涓婁紶鐨勬枃浠跺悕鏈�闀縶0}涓瓧绗�
+
+##鏉冮檺
+no.permission=鎮ㄦ病鏈夋暟鎹殑鏉冮檺锛岃鑱旂郴绠$悊鍛樻坊鍔犳潈闄� [{0}]
+no.create.permission=鎮ㄦ病鏈夊垱寤烘暟鎹殑鏉冮檺锛岃鑱旂郴绠$悊鍛樻坊鍔犳潈闄� [{0}]
+no.update.permission=鎮ㄦ病鏈変慨鏀规暟鎹殑鏉冮檺锛岃鑱旂郴绠$悊鍛樻坊鍔犳潈闄� [{0}]
+no.delete.permission=鎮ㄦ病鏈夊垹闄ゆ暟鎹殑鏉冮檺锛岃鑱旂郴绠$悊鍛樻坊鍔犳潈闄� [{0}]
+no.export.permission=鎮ㄦ病鏈夊鍑烘暟鎹殑鏉冮檺锛岃鑱旂郴绠$悊鍛樻坊鍔犳潈闄� [{0}]
+no.view.permission=鎮ㄦ病鏈夋煡鐪嬫暟鎹殑鏉冮檺锛岃鑱旂郴绠$悊鍛樻坊鍔犳潈闄� [{0}]
diff --git a/jcdm-admin/src/main/resources/logback.xml b/jcdm-admin/src/main/resources/logback.xml
new file mode 100644
index 0000000..6538681
--- /dev/null
+++ b/jcdm-admin/src/main/resources/logback.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+    <!-- 鏃ュ織瀛樻斁璺緞 -->
+	<property name="log.path" value="/home/mes/logs" />
+    <!-- 鏃ュ織杈撳嚭鏍煎紡 -->
+	<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
+
+	<!-- 鎺у埗鍙拌緭鍑� -->
+	<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
+		<encoder>
+			<pattern>${log.pattern}</pattern>
+		</encoder>
+	</appender>
+	
+	<!-- 绯荤粺鏃ュ織杈撳嚭 -->
+	<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
+	    <file>${log.path}/sys-info.log</file>
+        <!-- 寰幆鏀跨瓥锛氬熀浜庢椂闂村垱寤烘棩蹇楁枃浠� -->
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 鏃ュ織鏂囦欢鍚嶆牸寮� -->
+			<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
+			<!-- 鏃ュ織鏈�澶х殑鍘嗗彶 60澶� -->
+			<maxHistory>60</maxHistory>
+		</rollingPolicy>
+		<encoder>
+			<pattern>${log.pattern}</pattern>
+		</encoder>
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <!-- 杩囨护鐨勭骇鍒� -->
+            <level>INFO</level>
+            <!-- 鍖归厤鏃剁殑鎿嶄綔锛氭帴鏀讹紙璁板綍锛� -->
+            <onMatch>ACCEPT</onMatch>
+            <!-- 涓嶅尮閰嶆椂鐨勬搷浣滐細鎷掔粷锛堜笉璁板綍锛� -->
+            <onMismatch>DENY</onMismatch>
+        </filter>
+	</appender>
+	
+	<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
+	    <file>${log.path}/sys-error.log</file>
+        <!-- 寰幆鏀跨瓥锛氬熀浜庢椂闂村垱寤烘棩蹇楁枃浠� -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 鏃ュ織鏂囦欢鍚嶆牸寮� -->
+            <fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
+			<!-- 鏃ュ織鏈�澶х殑鍘嗗彶 60澶� -->
+			<maxHistory>60</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+        </encoder>
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <!-- 杩囨护鐨勭骇鍒� -->
+            <level>ERROR</level>
+			<!-- 鍖归厤鏃剁殑鎿嶄綔锛氭帴鏀讹紙璁板綍锛� -->
+            <onMatch>ACCEPT</onMatch>
+			<!-- 涓嶅尮閰嶆椂鐨勬搷浣滐細鎷掔粷锛堜笉璁板綍锛� -->
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+	
+	<!-- 鐢ㄦ埛璁块棶鏃ュ織杈撳嚭  -->
+    <appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<file>${log.path}/sys-user.log</file>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 鎸夊ぉ鍥炴粴 daily -->
+            <fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern>
+            <!-- 鏃ュ織鏈�澶х殑鍘嗗彶 60澶� -->
+            <maxHistory>60</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+        </encoder>
+    </appender>
+	
+	<!-- 绯荤粺妯″潡鏃ュ織绾у埆鎺у埗  -->
+	<logger name="com.jcdm" level="info" />
+	<!-- Spring鏃ュ織绾у埆鎺у埗  -->
+	<logger name="org.springframework" level="warn" />
+
+	<root level="info">
+		<appender-ref ref="console" />
+	</root>
+	
+	<!--绯荤粺鎿嶄綔鏃ュ織-->
+    <root level="info">
+        <appender-ref ref="file_info" />
+        <appender-ref ref="file_error" />
+    </root>
+	
+	<!--绯荤粺鐢ㄦ埛鎿嶄綔鏃ュ織-->
+    <logger name="sys-user" level="info">
+        <appender-ref ref="sys-user"/>
+    </logger>
+</configuration> 
\ No newline at end of file
diff --git a/jcdm-admin/src/main/resources/mybatis/mybatis-config.xml b/jcdm-admin/src/main/resources/mybatis/mybatis-config.xml
new file mode 100644
index 0000000..ac47c03
--- /dev/null
+++ b/jcdm-admin/src/main/resources/mybatis/mybatis-config.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE configuration
+PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-config.dtd">
+<configuration>
+    <!-- 鍏ㄥ眬鍙傛暟 -->
+    <settings>
+        <!-- 浣垮叏灞�鐨勬槧灏勫櫒鍚敤鎴栫鐢ㄧ紦瀛� -->
+        <setting name="cacheEnabled"             value="true"   />
+        <!-- 鍏佽JDBC 鏀寔鑷姩鐢熸垚涓婚敭 -->
+        <setting name="useGeneratedKeys"         value="true"   />
+        <!-- 閰嶇疆榛樿鐨勬墽琛屽櫒.SIMPLE灏辨槸鏅�氭墽琛屽櫒;REUSE鎵ц鍣ㄤ細閲嶇敤棰勫鐞嗚鍙�(prepared statements);BATCH鎵ц鍣ㄥ皢閲嶇敤璇彞骞舵墽琛屾壒閲忔洿鏂� -->
+        <setting name="defaultExecutorType"      value="SIMPLE" />
+		<!-- 鎸囧畾 MyBatis 鎵�鐢ㄦ棩蹇楃殑鍏蜂綋瀹炵幇 -->
+        <setting name="logImpl"                  value="SLF4J"  />
+        <!-- 浣跨敤椹煎嘲鍛藉悕娉曡浆鎹㈠瓧娈� -->
+		<!-- <setting name="mapUnderscoreToCamelCase" value="true"/> -->
+	</settings>
+	
+</configuration>
diff --git a/jcdm-common/pom.xml b/jcdm-common/pom.xml
new file mode 100644
index 0000000..dc47c56
--- /dev/null
+++ b/jcdm-common/pom.xml
@@ -0,0 +1,145 @@
+<?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">
+    <parent>
+        <artifactId>jcdm</artifactId>
+        <groupId>com.jcdm</groupId>
+        <version>3.8.6</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>jcdm-common</artifactId>
+
+    <description>
+        common閫氱敤宸ュ叿
+    </description>
+
+    <dependencies>
+
+        <!-- Spring妗嗘灦鍩烘湰鐨勬牳蹇冨伐鍏� -->
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context-support</artifactId>
+        </dependency>
+
+        <!-- SpringWeb妯″潡 -->
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-web</artifactId>
+        </dependency>
+
+        <!-- spring security 瀹夊叏璁よ瘉 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-security</artifactId>
+        </dependency>
+
+        <!-- pagehelper 鍒嗛〉鎻掍欢 -->
+        <dependency>
+            <groupId>com.github.pagehelper</groupId>
+            <artifactId>pagehelper-spring-boot-starter</artifactId>
+        </dependency>
+
+        <!-- mybatis-plus 澧炲己CRUD -->
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+            <version>3.4.2</version>
+        </dependency>
+
+        <!-- 鑷畾涔夐獙璇佹敞瑙� -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-validation</artifactId>
+        </dependency>
+
+        <!--甯哥敤宸ュ叿绫� -->
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+  
+        <!-- JSON宸ュ叿绫� -->
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+        </dependency>
+        
+        <!-- 鍔ㄦ�佹暟鎹簮 -->
+		<dependency>
+			<groupId>com.baomidou</groupId>
+			<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
+			<version>3.5.2</version>
+		</dependency>
+
+        <!-- 闃块噷JSON瑙f瀽鍣� -->
+        <dependency>
+            <groupId>com.alibaba.fastjson2</groupId>
+            <artifactId>fastjson2</artifactId>
+        </dependency>
+
+        <!-- io甯哥敤宸ュ叿绫� -->
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+        </dependency>
+
+        <!-- excel宸ュ叿 -->
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml</artifactId>
+        </dependency>
+
+        <!-- yml瑙f瀽鍣� -->
+        <dependency>
+            <groupId>org.yaml</groupId>
+            <artifactId>snakeyaml</artifactId>
+        </dependency>
+
+        <!-- Token鐢熸垚涓庤В鏋�-->
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt</artifactId>
+        </dependency>
+
+        <!-- Jaxb -->
+        <dependency>
+            <groupId>javax.xml.bind</groupId>
+            <artifactId>jaxb-api</artifactId>
+        </dependency>
+
+        <!-- redis 缂撳瓨鎿嶄綔 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+
+        <!-- pool 瀵硅薄姹� -->
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-pool2</artifactId>
+        </dependency>
+
+        <!-- 瑙f瀽瀹㈡埛绔搷浣滅郴缁熴�佹祻瑙堝櫒绛� -->
+        <dependency>
+            <groupId>eu.bitwalker</groupId>
+            <artifactId>UserAgentUtils</artifactId>
+        </dependency>
+
+        <!-- servlet鍖� -->
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+        </dependency>
+
+        <!-- mybatis-plus 澧炲己CRUD -->
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+            <version>3.4.1</version>
+        </dependency>
+
+    </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/jcdm-common/src/main/java/com/jcdm/common/annotation/Anonymous.java b/jcdm-common/src/main/java/com/jcdm/common/annotation/Anonymous.java
new file mode 100644
index 0000000..226b276
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/annotation/Anonymous.java
@@ -0,0 +1,19 @@
+package com.jcdm.common.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 鍖垮悕璁块棶涓嶉壌鏉冩敞瑙�
+ * 
+ * @author jc
+ */
+@Target({ ElementType.METHOD, ElementType.TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface Anonymous
+{
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/annotation/DataScope.java b/jcdm-common/src/main/java/com/jcdm/common/annotation/DataScope.java
new file mode 100644
index 0000000..235a558
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/annotation/DataScope.java
@@ -0,0 +1,33 @@
+package com.jcdm.common.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 鏁版嵁鏉冮檺杩囨护娉ㄨВ
+ * 
+ * @author jc
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface DataScope
+{
+    /**
+     * 閮ㄩ棬琛ㄧ殑鍒悕
+     */
+    public String deptAlias() default "";
+
+    /**
+     * 鐢ㄦ埛琛ㄧ殑鍒悕
+     */
+    public String userAlias() default "";
+
+    /**
+     * 鏉冮檺瀛楃锛堢敤浜庡涓鑹插尮閰嶇鍚堣姹傜殑鏉冮檺锛夐粯璁ゆ牴鎹潈闄愭敞瑙ss鑾峰彇锛屽涓潈闄愮敤閫楀彿鍒嗛殧寮�鏉�
+     */
+    public String permission() default "";
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/annotation/DataSource.java b/jcdm-common/src/main/java/com/jcdm/common/annotation/DataSource.java
new file mode 100644
index 0000000..dcece60
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/annotation/DataSource.java
@@ -0,0 +1,28 @@
+package com.jcdm.common.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import com.jcdm.common.enums.DataSourceType;
+
+/**
+ * 鑷畾涔夊鏁版嵁婧愬垏鎹㈡敞瑙�
+ *
+ * 浼樺厛绾э細鍏堟柟娉曪紝鍚庣被锛屽鏋滄柟娉曡鐩栦簡绫讳笂鐨勬暟鎹簮绫诲瀷锛屼互鏂规硶鐨勪负鍑嗭紝鍚﹀垯浠ョ被涓婄殑涓哄噯
+ *
+ * @author jc
+ */
+@Target({ ElementType.METHOD, ElementType.TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+public @interface DataSource
+{
+    /**
+     * 鍒囨崲鏁版嵁婧愬悕绉�
+     */
+    public DataSourceType value() default DataSourceType.MASTER;
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/annotation/Excel.java b/jcdm-common/src/main/java/com/jcdm/common/annotation/Excel.java
new file mode 100644
index 0000000..9fc8992
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/annotation/Excel.java
@@ -0,0 +1,187 @@
+package com.jcdm.common.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.math.BigDecimal;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.apache.poi.ss.usermodel.IndexedColors;
+import com.jcdm.common.utils.poi.ExcelHandlerAdapter;
+
+/**
+ * 鑷畾涔夊鍑篍xcel鏁版嵁娉ㄨВ
+ * 
+ * @author jc
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface Excel
+{
+    /**
+     * 瀵煎嚭鏃跺湪excel涓帓搴�
+     */
+    public int sort() default Integer.MAX_VALUE;
+
+    /**
+     * 瀵煎嚭鍒癊xcel涓殑鍚嶅瓧.
+     */
+    public String name() default "";
+
+    /**
+     * 鏃ユ湡鏍煎紡, 濡�: yyyy-MM-dd
+     */
+    public String dateFormat() default "";
+
+    /**
+     * 濡傛灉鏄瓧鍏哥被鍨嬶紝璇疯缃瓧鍏哥殑type鍊� (濡�: sys_user_sex)
+     */
+    public String dictType() default "";
+
+    /**
+     * 璇诲彇鍐呭杞〃杈惧紡 (濡�: 0=鐢�,1=濂�,2=鏈煡)
+     */
+    public String readConverterExp() default "";
+
+    /**
+     * 鍒嗛殧绗︼紝璇诲彇瀛楃涓茬粍鍐呭
+     */
+    public String separator() default ",";
+
+    /**
+     * BigDecimal 绮惧害 榛樿:-1(榛樿涓嶅紑鍚疊igDecimal鏍煎紡鍖�)
+     */
+    public int scale() default -1;
+
+    /**
+     * BigDecimal 鑸嶅叆瑙勫垯 榛樿:BigDecimal.ROUND_HALF_EVEN
+     */
+    public int roundingMode() default BigDecimal.ROUND_HALF_EVEN;
+
+    /**
+     * 瀵煎嚭鏃跺湪excel涓瘡涓垪鐨勯珮搴�
+     */
+    public double height() default 14;
+
+    /**
+     * 瀵煎嚭鏃跺湪excel涓瘡涓垪鐨勫搴�
+     */
+    public double width() default 16;
+
+    /**
+     * 鏂囧瓧鍚庣紑,濡�% 90 鍙樻垚90%
+     */
+    public String suffix() default "";
+
+    /**
+     * 褰撳�间负绌烘椂,瀛楁鐨勯粯璁ゅ��
+     */
+    public String defaultValue() default "";
+
+    /**
+     * 鎻愮ず淇℃伅
+     */
+    public String prompt() default "";
+
+    /**
+     * 璁剧疆鍙兘閫夋嫨涓嶈兘杈撳叆鐨勫垪鍐呭.
+     */
+    public String[] combo() default {};
+
+    /**
+     * 鏄惁闇�瑕佺旱鍚戝悎骞跺崟鍏冩牸,搴斿闇�姹�:鍚湁list闆嗗悎鍗曞厓鏍�)
+     */
+    public boolean needMerge() default false;
+
+    /**
+     * 鏄惁瀵煎嚭鏁版嵁,搴斿闇�姹�:鏈夋椂鎴戜滑闇�瑕佸鍑轰竴浠芥ā鏉�,杩欐槸鏍囬闇�瑕佷絾鍐呭闇�瑕佺敤鎴锋墜宸ュ~鍐�.
+     */
+    public boolean isExport() default true;
+
+    /**
+     * 鍙︿竴涓被涓殑灞炴�у悕绉�,鏀寔澶氱骇鑾峰彇,浠ュ皬鏁扮偣闅斿紑
+     */
+    public String targetAttr() default "";
+
+    /**
+     * 鏄惁鑷姩缁熻鏁版嵁,鍦ㄦ渶鍚庤拷鍔犱竴琛岀粺璁℃暟鎹�诲拰
+     */
+    public boolean isStatistics() default false;
+
+    /**
+     * 瀵煎嚭绫诲瀷锛�0鏁板瓧 1瀛楃涓� 2鍥剧墖锛�
+     */
+    public ColumnType cellType() default ColumnType.STRING;
+
+    /**
+     * 瀵煎嚭鍒楀ご鑳屾櫙棰滆壊
+     */
+    public IndexedColors headerBackgroundColor() default IndexedColors.GREY_50_PERCENT;
+
+    /**
+     * 瀵煎嚭鍒楀ご瀛椾綋棰滆壊
+     */
+    public IndexedColors headerColor() default IndexedColors.WHITE;
+
+    /**
+     * 瀵煎嚭鍗曞厓鏍艰儗鏅鑹�
+     */
+    public IndexedColors backgroundColor() default IndexedColors.WHITE;
+
+    /**
+     * 瀵煎嚭鍗曞厓鏍煎瓧浣撻鑹�
+     */
+    public IndexedColors color() default IndexedColors.BLACK;
+
+    /**
+     * 瀵煎嚭瀛楁瀵归綈鏂瑰紡
+     */
+    public HorizontalAlignment align() default HorizontalAlignment.CENTER;
+
+    /**
+     * 鑷畾涔夋暟鎹鐞嗗櫒
+     */
+    public Class<?> handler() default ExcelHandlerAdapter.class;
+
+    /**
+     * 鑷畾涔夋暟鎹鐞嗗櫒鍙傛暟
+     */
+    public String[] args() default {};
+
+    /**
+     * 瀛楁绫诲瀷锛�0锛氬鍑哄鍏ワ紱1锛氫粎瀵煎嚭锛�2锛氫粎瀵煎叆锛�
+     */
+    Type type() default Type.ALL;
+
+    public enum Type
+    {
+        ALL(0), EXPORT(1), IMPORT(2);
+        private final int value;
+
+        Type(int value)
+        {
+            this.value = value;
+        }
+
+        public int value()
+        {
+            return this.value;
+        }
+    }
+
+    public enum ColumnType
+    {
+        NUMERIC(0), STRING(1), IMAGE(2);
+        private final int value;
+
+        ColumnType(int value)
+        {
+            this.value = value;
+        }
+
+        public int value()
+        {
+            return this.value;
+        }
+    }
+}
\ No newline at end of file
diff --git a/jcdm-common/src/main/java/com/jcdm/common/annotation/Excels.java b/jcdm-common/src/main/java/com/jcdm/common/annotation/Excels.java
new file mode 100644
index 0000000..093be54
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/annotation/Excels.java
@@ -0,0 +1,18 @@
+package com.jcdm.common.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Excel娉ㄨВ闆�
+ * 
+ * @author jc
+ */
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Excels
+{
+    public Excel[] value();
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/annotation/Log.java b/jcdm-common/src/main/java/com/jcdm/common/annotation/Log.java
new file mode 100644
index 0000000..8738251
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/annotation/Log.java
@@ -0,0 +1,51 @@
+package com.jcdm.common.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.common.enums.OperatorType;
+
+/**
+ * 鑷畾涔夋搷浣滄棩蹇楄褰曟敞瑙�
+ * 
+ * @author jc
+ *
+ */
+@Target({ ElementType.PARAMETER, ElementType.METHOD })
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface Log
+{
+    /**
+     * 妯″潡
+     */
+    public String title() default "";
+
+    /**
+     * 鍔熻兘
+     */
+    public BusinessType businessType() default BusinessType.OTHER;
+
+    /**
+     * 鎿嶄綔浜虹被鍒�
+     */
+    public OperatorType operatorType() default OperatorType.MANAGE;
+
+    /**
+     * 鏄惁淇濆瓨璇锋眰鐨勫弬鏁�
+     */
+    public boolean isSaveRequestData() default true;
+
+    /**
+     * 鏄惁淇濆瓨鍝嶅簲鐨勫弬鏁�
+     */
+    public boolean isSaveResponseData() default true;
+
+    /**
+     * 鎺掗櫎鎸囧畾鐨勮姹傚弬鏁�
+     */
+    public String[] excludeParamNames() default {};
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/annotation/RateLimiter.java b/jcdm-common/src/main/java/com/jcdm/common/annotation/RateLimiter.java
new file mode 100644
index 0000000..a6cd783
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/annotation/RateLimiter.java
@@ -0,0 +1,40 @@
+package com.jcdm.common.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import com.jcdm.common.constant.CacheConstants;
+import com.jcdm.common.enums.LimitType;
+
+/**
+ * 闄愭祦娉ㄨВ
+ * 
+ * @author jc
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface RateLimiter
+{
+    /**
+     * 闄愭祦key
+     */
+    public String key() default CacheConstants.RATE_LIMIT_KEY;
+
+    /**
+     * 闄愭祦鏃堕棿,鍗曚綅绉�
+     */
+    public int time() default 60;
+
+    /**
+     * 闄愭祦娆℃暟
+     */
+    public int count() default 100;
+
+    /**
+     * 闄愭祦绫诲瀷
+     */
+    public LimitType limitType() default LimitType.DEFAULT;
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/annotation/RepeatSubmit.java b/jcdm-common/src/main/java/com/jcdm/common/annotation/RepeatSubmit.java
new file mode 100644
index 0000000..fddefeb
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/annotation/RepeatSubmit.java
@@ -0,0 +1,31 @@
+package com.jcdm.common.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 鑷畾涔夋敞瑙i槻姝㈣〃鍗曢噸澶嶆彁浜�
+ * 
+ * @author jc
+ *
+ */
+@Inherited
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface RepeatSubmit
+{
+    /**
+     * 闂撮殧鏃堕棿(ms)锛屽皬浜庢鏃堕棿瑙嗕负閲嶅鎻愪氦
+     */
+    public int interval() default 5000;
+
+    /**
+     * 鎻愮ず娑堟伅
+     */
+    public String message() default "涓嶅厑璁搁噸澶嶆彁浜わ紝璇风◢鍊欏啀璇�";
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/config/MesConfig.java b/jcdm-common/src/main/java/com/jcdm/common/config/MesConfig.java
new file mode 100644
index 0000000..5d3eb00
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/config/MesConfig.java
@@ -0,0 +1,135 @@
+package com.jcdm.common.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * 璇诲彇椤圭洰鐩稿叧閰嶇疆
+ * 
+ * @author jc
+ */
+@Component
+@ConfigurationProperties(prefix = "ruoyi")
+public class MesConfig
+{
+    /** 椤圭洰鍚嶇О */
+    private String name;
+
+    /** 鐗堟湰 */
+    private String version;
+
+    /** 鐗堟潈骞翠唤 */
+    private String copyrightYear;
+
+    /** 瀹炰緥婕旂ず寮�鍏� */
+    private boolean demoEnabled;
+
+    /** 涓婁紶璺緞 */
+    private static String profile;
+
+    /** 鑾峰彇鍦板潃寮�鍏� */
+    private static boolean addressEnabled;
+
+    /** 楠岃瘉鐮佺被鍨� */
+    private static String captchaType;
+
+    public String getName()
+    {
+        return name;
+    }
+
+    public void setName(String name)
+    {
+        this.name = name;
+    }
+
+    public String getVersion()
+    {
+        return version;
+    }
+
+    public void setVersion(String version)
+    {
+        this.version = version;
+    }
+
+    public String getCopyrightYear()
+    {
+        return copyrightYear;
+    }
+
+    public void setCopyrightYear(String copyrightYear)
+    {
+        this.copyrightYear = copyrightYear;
+    }
+
+    public boolean isDemoEnabled()
+    {
+        return demoEnabled;
+    }
+
+    public void setDemoEnabled(boolean demoEnabled)
+    {
+        this.demoEnabled = demoEnabled;
+    }
+
+    public static String getProfile()
+    {
+        return profile;
+    }
+
+    public void setProfile(String profile)
+    {
+        MesConfig.profile = profile;
+    }
+
+    public static boolean isAddressEnabled()
+    {
+        return addressEnabled;
+    }
+
+    public void setAddressEnabled(boolean addressEnabled)
+    {
+        MesConfig.addressEnabled = addressEnabled;
+    }
+
+    public static String getCaptchaType() {
+        return captchaType;
+    }
+
+    public void setCaptchaType(String captchaType) {
+        MesConfig.captchaType = captchaType;
+    }
+
+    /**
+     * 鑾峰彇瀵煎叆涓婁紶璺緞
+     */
+    public static String getImportPath()
+    {
+        return getProfile() + "/import";
+    }
+
+    /**
+     * 鑾峰彇澶村儚涓婁紶璺緞
+     */
+    public static String getAvatarPath()
+    {
+        return getProfile() + "/avatar";
+    }
+
+    /**
+     * 鑾峰彇涓嬭浇璺緞
+     */
+    public static String getDownloadPath()
+    {
+        return getProfile() + "/download/";
+    }
+
+    /**
+     * 鑾峰彇涓婁紶璺緞
+     */
+    public static String getUploadPath()
+    {
+        return getProfile() + "/upload";
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/constant/CacheConstants.java b/jcdm-common/src/main/java/com/jcdm/common/constant/CacheConstants.java
new file mode 100644
index 0000000..7ef7b4c
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/constant/CacheConstants.java
@@ -0,0 +1,44 @@
+package com.jcdm.common.constant;
+
+/**
+ * 缂撳瓨鐨刱ey 甯搁噺
+ * 
+ * @author jc
+ */
+public class CacheConstants
+{
+    /**
+     * 鐧诲綍鐢ㄦ埛 redis key
+     */
+    public static final String LOGIN_TOKEN_KEY = "login_tokens:";
+
+    /**
+     * 楠岃瘉鐮� redis key
+     */
+    public static final String CAPTCHA_CODE_KEY = "captcha_codes:";
+
+    /**
+     * 鍙傛暟绠$悊 cache key
+     */
+    public static final String SYS_CONFIG_KEY = "sys_config:";
+
+    /**
+     * 瀛楀吀绠$悊 cache key
+     */
+    public static final String SYS_DICT_KEY = "sys_dict:";
+
+    /**
+     * 闃查噸鎻愪氦 redis key
+     */
+    public static final String REPEAT_SUBMIT_KEY = "repeat_submit:";
+
+    /**
+     * 闄愭祦 redis key
+     */
+    public static final String RATE_LIMIT_KEY = "rate_limit:";
+
+    /**
+     * 鐧诲綍璐︽埛瀵嗙爜閿欒娆℃暟 redis key
+     */
+    public static final String PWD_ERR_CNT_KEY = "pwd_err_cnt:";
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/constant/Constants.java b/jcdm-common/src/main/java/com/jcdm/common/constant/Constants.java
new file mode 100644
index 0000000..993ff65
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/constant/Constants.java
@@ -0,0 +1,167 @@
+package com.jcdm.common.constant;
+
+import io.jsonwebtoken.Claims;
+
+/**
+ * 閫氱敤甯搁噺淇℃伅
+ * 
+ * @author jc
+ */
+public class Constants
+{
+    /**
+     * UTF-8 瀛楃闆�
+     */
+    public static final String UTF8 = "UTF-8";
+
+    /**
+     * GBK 瀛楃闆�
+     */
+    public static final String GBK = "GBK";
+
+    /**
+     * www涓诲煙
+     */
+    public static final String WWW = "www.";
+
+    /**
+     * http璇锋眰
+     */
+    public static final String HTTP = "http://";
+
+    /**
+     * https璇锋眰
+     */
+    public static final String HTTPS = "https://";
+
+    /**
+     * 閫氱敤鎴愬姛鏍囪瘑
+     */
+    public static final String SUCCESS = "0";
+
+    /**
+     * 閫氱敤澶辫触鏍囪瘑
+     */
+    public static final String FAIL = "1";
+
+    /**
+     * 鐧诲綍鎴愬姛
+     */
+    public static final String LOGIN_SUCCESS = "Success";
+
+    /**
+     * 娉ㄩ攢
+     */
+    public static final String LOGOUT = "Logout";
+
+    /**
+     * 娉ㄥ唽
+     */
+    public static final String REGISTER = "Register";
+
+    /**
+     * 鐧诲綍澶辫触
+     */
+    public static final String LOGIN_FAIL = "Error";
+
+    /**
+     * 鎵�鏈夋潈闄愭爣璇�
+     */
+    public static final String ALL_PERMISSION = "*:*:*";
+
+    /**
+     * 绠$悊鍛樿鑹叉潈闄愭爣璇�
+     */
+    public static final String SUPER_ADMIN = "admin";
+
+    /**
+     * 瑙掕壊鏉冮檺鍒嗛殧绗�
+     */
+    public static final String ROLE_DELIMETER = ",";
+
+    /**
+     * 鏉冮檺鏍囪瘑鍒嗛殧绗�
+     */
+    public static final String PERMISSION_DELIMETER = ",";
+
+    /**
+     * 楠岃瘉鐮佹湁鏁堟湡锛堝垎閽燂級
+     */
+    public static final Integer CAPTCHA_EXPIRATION = 2;
+
+    /**
+     * 浠ょ墝
+     */
+    public static final String TOKEN = "token";
+
+    /**
+     * 浠ょ墝鍓嶇紑
+     */
+    public static final String TOKEN_PREFIX = "Bearer ";
+
+    /**
+     * 浠ょ墝鍓嶇紑
+     */
+    public static final String LOGIN_USER_KEY = "login_user_key";
+
+    /**
+     * 鐢ㄦ埛ID
+     */
+    public static final String JWT_USERID = "userid";
+
+    /**
+     * 鐢ㄦ埛鍚嶇О
+     */
+    public static final String JWT_USERNAME = Claims.SUBJECT;
+
+    /**
+     * 鐢ㄦ埛澶村儚
+     */
+    public static final String JWT_AVATAR = "avatar";
+
+    /**
+     * 鍒涘缓鏃堕棿
+     */
+    public static final String JWT_CREATED = "created";
+
+    /**
+     * 鐢ㄦ埛鏉冮檺
+     */
+    public static final String JWT_AUTHORITIES = "authorities";
+
+    /**
+     * 璧勬簮鏄犲皠璺緞 鍓嶇紑
+     */
+    public static final String RESOURCE_PREFIX = "/profile";
+
+    /**
+     * RMI 杩滅▼鏂规硶璋冪敤
+     */
+    public static final String LOOKUP_RMI = "rmi:";
+
+    /**
+     * LDAP 杩滅▼鏂规硶璋冪敤
+     */
+    public static final String LOOKUP_LDAP = "ldap:";
+
+    /**
+     * LDAPS 杩滅▼鏂规硶璋冪敤
+     */
+    public static final String LOOKUP_LDAPS = "ldaps:";
+
+    /**
+     * 鑷姩璇嗗埆json瀵硅薄鐧藉悕鍗曢厤缃紙浠呭厑璁歌В鏋愮殑鍖呭悕锛岃寖鍥磋秺灏忚秺瀹夊叏锛�
+     */
+    public static final String[] JSON_WHITELIST_STR = { "org.springframework", "com.jcdm" };
+
+    /**
+     * 瀹氭椂浠诲姟鐧藉悕鍗曢厤缃紙浠呭厑璁歌闂殑鍖呭悕锛屽鍏朵粬闇�瑕佸彲浠ヨ嚜琛屾坊鍔狅級
+     */
+    public static final String[] JOB_WHITELIST_STR = { "com.jcdm" };
+
+    /**
+     * 瀹氭椂浠诲姟杩濊鐨勫瓧绗�
+     */
+    public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
+            "org.springframework", "org.apache", "com.jcdm.common.utils.file", "com.jcdm.common.config" };
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/constant/GenConstants.java b/jcdm-common/src/main/java/com/jcdm/common/constant/GenConstants.java
new file mode 100644
index 0000000..76eb41a
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/constant/GenConstants.java
@@ -0,0 +1,117 @@
+package com.jcdm.common.constant;
+
+/**
+ * 浠g爜鐢熸垚閫氱敤甯搁噺
+ * 
+ * @author jc
+ */
+public class GenConstants
+{
+    /** 鍗曡〃锛堝鍒犳敼鏌ワ級 */
+    public static final String TPL_CRUD = "crud";
+
+    /** 鏍戣〃锛堝鍒犳敼鏌ワ級 */
+    public static final String TPL_TREE = "tree";
+
+    /** 涓诲瓙琛紙澧炲垹鏀规煡锛� */
+    public static final String TPL_SUB = "sub";
+
+    /** 鏍戠紪鐮佸瓧娈� */
+    public static final String TREE_CODE = "treeCode";
+
+    /** 鏍戠埗缂栫爜瀛楁 */
+    public static final String TREE_PARENT_CODE = "treeParentCode";
+
+    /** 鏍戝悕绉板瓧娈� */
+    public static final String TREE_NAME = "treeName";
+
+    /** 涓婄骇鑿滃崟ID瀛楁 */
+    public static final String PARENT_MENU_ID = "parentMenuId";
+
+    /** 涓婄骇鑿滃崟鍚嶇О瀛楁 */
+    public static final String PARENT_MENU_NAME = "parentMenuName";
+
+    /** 鏁版嵁搴撳瓧绗︿覆绫诲瀷 */
+    public static final String[] COLUMNTYPE_STR = { "char", "varchar", "nvarchar", "varchar2" };
+
+    /** 鏁版嵁搴撴枃鏈被鍨� */
+    public static final String[] COLUMNTYPE_TEXT = { "tinytext", "text", "mediumtext", "longtext" };
+
+    /** 鏁版嵁搴撴椂闂寸被鍨� */
+    public static final String[] COLUMNTYPE_TIME = { "datetime", "time", "date", "timestamp" };
+
+    /** 鏁版嵁搴撴暟瀛楃被鍨� */
+    public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer",
+            "bit", "bigint", "float", "double", "decimal" };
+
+    /** 椤甸潰涓嶉渶瑕佺紪杈戝瓧娈� */
+    public static final String[] COLUMNNAME_NOT_EDIT = { "id", "create_by", "create_time", "del_flag" };
+
+    /** 椤甸潰涓嶉渶瑕佹樉绀虹殑鍒楄〃瀛楁 */
+    public static final String[] COLUMNNAME_NOT_LIST = { "id", "create_by", "create_time", "del_flag", "update_by",
+            "update_time" };
+
+    /** 椤甸潰涓嶉渶瑕佹煡璇㈠瓧娈� */
+    public static final String[] COLUMNNAME_NOT_QUERY = { "id", "create_by", "create_time", "del_flag", "update_by",
+            "update_time", "remark" };
+
+    /** Entity鍩虹被瀛楁 */
+    public static final String[] BASE_ENTITY = { "createBy", "createTime", "updateBy", "updateTime", "remark" };
+
+    /** Tree鍩虹被瀛楁 */
+    public static final String[] TREE_ENTITY = { "parentName", "parentId", "orderNum", "ancestors", "children" };
+
+    /** 鏂囨湰妗� */
+    public static final String HTML_INPUT = "input";
+
+    /** 鏂囨湰鍩� */
+    public static final String HTML_TEXTAREA = "textarea";
+
+    /** 涓嬫媺妗� */
+    public static final String HTML_SELECT = "select";
+
+    /** 鍗曢�夋 */
+    public static final String HTML_RADIO = "radio";
+
+    /** 澶嶉�夋 */
+    public static final String HTML_CHECKBOX = "checkbox";
+
+    /** 鏃ユ湡鎺т欢 */
+    public static final String HTML_DATETIME = "datetime";
+
+    /** 鍥剧墖涓婁紶鎺т欢 */
+    public static final String HTML_IMAGE_UPLOAD = "imageUpload";
+
+    /** 鏂囦欢涓婁紶鎺т欢 */
+    public static final String HTML_FILE_UPLOAD = "fileUpload";
+
+    /** 瀵屾枃鏈帶浠� */
+    public static final String HTML_EDITOR = "editor";
+
+    /** 瀛楃涓茬被鍨� */
+    public static final String TYPE_STRING = "String";
+
+    /** 鏁村瀷 */
+    public static final String TYPE_INTEGER = "Integer";
+
+    /** 闀挎暣鍨� */
+    public static final String TYPE_LONG = "Long";
+
+    /** 娴偣鍨� */
+    public static final String TYPE_DOUBLE = "Double";
+
+    /** 楂樼簿搴﹁绠楃被鍨� */
+    public static final String TYPE_BIGDECIMAL = "BigDecimal";
+
+    /** 鏃堕棿绫诲瀷 */
+    public static final String TYPE_DATE = "Date";
+
+    /** 妯$硦鏌ヨ */
+    public static final String QUERY_LIKE = "LIKE";
+
+    /** 鐩哥瓑鏌ヨ */
+    public static final String QUERY_EQ = "EQ";
+
+    /** 闇�瑕� */
+    public static final String REQUIRE = "1";
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/constant/HttpStatus.java b/jcdm-common/src/main/java/com/jcdm/common/constant/HttpStatus.java
new file mode 100644
index 0000000..15538ba
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/constant/HttpStatus.java
@@ -0,0 +1,94 @@
+package com.jcdm.common.constant;
+
+/**
+ * 杩斿洖鐘舵�佺爜
+ * 
+ * @author jc
+ */
+public class HttpStatus
+{
+    /**
+     * 鎿嶄綔鎴愬姛
+     */
+    public static final int SUCCESS = 200;
+
+    /**
+     * 瀵硅薄鍒涘缓鎴愬姛
+     */
+    public static final int CREATED = 201;
+
+    /**
+     * 璇锋眰宸茬粡琚帴鍙�
+     */
+    public static final int ACCEPTED = 202;
+
+    /**
+     * 鎿嶄綔宸茬粡鎵ц鎴愬姛锛屼絾鏄病鏈夎繑鍥炴暟鎹�
+     */
+    public static final int NO_CONTENT = 204;
+
+    /**
+     * 璧勬簮宸茶绉婚櫎
+     */
+    public static final int MOVED_PERM = 301;
+
+    /**
+     * 閲嶅畾鍚�
+     */
+    public static final int SEE_OTHER = 303;
+
+    /**
+     * 璧勬簮娌℃湁琚慨鏀�
+     */
+    public static final int NOT_MODIFIED = 304;
+
+    /**
+     * 鍙傛暟鍒楄〃閿欒锛堢己灏戯紝鏍煎紡涓嶅尮閰嶏級
+     */
+    public static final int BAD_REQUEST = 400;
+
+    /**
+     * 鏈巿鏉�
+     */
+    public static final int UNAUTHORIZED = 401;
+
+    /**
+     * 璁块棶鍙楅檺锛屾巿鏉冭繃鏈�
+     */
+    public static final int FORBIDDEN = 403;
+
+    /**
+     * 璧勬簮锛屾湇鍔℃湭鎵惧埌
+     */
+    public static final int NOT_FOUND = 404;
+
+    /**
+     * 涓嶅厑璁哥殑http鏂规硶
+     */
+    public static final int BAD_METHOD = 405;
+
+    /**
+     * 璧勬簮鍐茬獊锛屾垨鑰呰祫婧愯閿�
+     */
+    public static final int CONFLICT = 409;
+
+    /**
+     * 涓嶆敮鎸佺殑鏁版嵁锛屽獟浣撶被鍨�
+     */
+    public static final int UNSUPPORTED_TYPE = 415;
+
+    /**
+     * 绯荤粺鍐呴儴閿欒
+     */
+    public static final int ERROR = 500;
+
+    /**
+     * 鎺ュ彛鏈疄鐜�
+     */
+    public static final int NOT_IMPLEMENTED = 501;
+
+    /**
+     * 绯荤粺璀﹀憡娑堟伅
+     */
+    public static final int WARN = 601;
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/constant/ScheduleConstants.java b/jcdm-common/src/main/java/com/jcdm/common/constant/ScheduleConstants.java
new file mode 100644
index 0000000..9170306
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/constant/ScheduleConstants.java
@@ -0,0 +1,50 @@
+package com.jcdm.common.constant;
+
+/**
+ * 浠诲姟璋冨害閫氱敤甯搁噺
+ * 
+ * @author jc
+ */
+public class ScheduleConstants
+{
+    public static final String TASK_CLASS_NAME = "TASK_CLASS_NAME";
+
+    /** 鎵ц鐩爣key */
+    public static final String TASK_PROPERTIES = "TASK_PROPERTIES";
+
+    /** 榛樿 */
+    public static final String MISFIRE_DEFAULT = "0";
+
+    /** 绔嬪嵆瑙﹀彂鎵ц */
+    public static final String MISFIRE_IGNORE_MISFIRES = "1";
+
+    /** 瑙﹀彂涓�娆℃墽琛� */
+    public static final String MISFIRE_FIRE_AND_PROCEED = "2";
+
+    /** 涓嶈Е鍙戠珛鍗虫墽琛� */
+    public static final String MISFIRE_DO_NOTHING = "3";
+
+    public enum Status
+    {
+        /**
+         * 姝e父
+         */
+        NORMAL("0"),
+        /**
+         * 鏆傚仠
+         */
+        PAUSE("1");
+
+        private String value;
+
+        private Status(String value)
+        {
+            this.value = value;
+        }
+
+        public String getValue()
+        {
+            return value;
+        }
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/constant/UserConstants.java b/jcdm-common/src/main/java/com/jcdm/common/constant/UserConstants.java
new file mode 100644
index 0000000..29ec565
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/constant/UserConstants.java
@@ -0,0 +1,78 @@
+package com.jcdm.common.constant;
+
+/**
+ * 鐢ㄦ埛甯搁噺淇℃伅
+ * 
+ * @author jc
+ */
+public class UserConstants
+{
+    /**
+     * 骞冲彴鍐呯郴缁熺敤鎴风殑鍞竴鏍囧織
+     */
+    public static final String SYS_USER = "SYS_USER";
+
+    /** 姝e父鐘舵�� */
+    public static final String NORMAL = "0";
+
+    /** 寮傚父鐘舵�� */
+    public static final String EXCEPTION = "1";
+
+    /** 鐢ㄦ埛灏佺鐘舵�� */
+    public static final String USER_DISABLE = "1";
+
+    /** 瑙掕壊灏佺鐘舵�� */
+    public static final String ROLE_DISABLE = "1";
+
+    /** 閮ㄩ棬姝e父鐘舵�� */
+    public static final String DEPT_NORMAL = "0";
+
+    /** 閮ㄩ棬鍋滅敤鐘舵�� */
+    public static final String DEPT_DISABLE = "1";
+
+    /** 瀛楀吀姝e父鐘舵�� */
+    public static final String DICT_NORMAL = "0";
+
+    /** 鏄惁涓虹郴缁熼粯璁わ紙鏄級 */
+    public static final String YES = "Y";
+
+    /** 鏄惁鑿滃崟澶栭摼锛堟槸锛� */
+    public static final String YES_FRAME = "0";
+
+    /** 鏄惁鑿滃崟澶栭摼锛堝惁锛� */
+    public static final String NO_FRAME = "1";
+
+    /** 鑿滃崟绫诲瀷锛堢洰褰曪級 */
+    public static final String TYPE_DIR = "M";
+
+    /** 鑿滃崟绫诲瀷锛堣彍鍗曪級 */
+    public static final String TYPE_MENU = "C";
+
+    /** 鑿滃崟绫诲瀷锛堟寜閽級 */
+    public static final String TYPE_BUTTON = "F";
+
+    /** Layout缁勪欢鏍囪瘑 */
+    public final static String LAYOUT = "Layout";
+    
+    /** ParentView缁勪欢鏍囪瘑 */
+    public final static String PARENT_VIEW = "ParentView";
+
+    /** InnerLink缁勪欢鏍囪瘑 */
+    public final static String INNER_LINK = "InnerLink";
+
+    /** 鏍¢獙鏄惁鍞竴鐨勮繑鍥炴爣璇� */
+    public final static boolean UNIQUE = true;
+    public final static boolean NOT_UNIQUE = false;
+
+    /**
+     * 鐢ㄦ埛鍚嶉暱搴﹂檺鍒�
+     */
+    public static final int USERNAME_MIN_LENGTH = 2;
+    public static final int USERNAME_MAX_LENGTH = 20;
+
+    /**
+     * 瀵嗙爜闀垮害闄愬埗
+     */
+    public static final int PASSWORD_MIN_LENGTH = 5;
+    public static final int PASSWORD_MAX_LENGTH = 20;
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/core/controller/BaseController.java b/jcdm-common/src/main/java/com/jcdm/common/core/controller/BaseController.java
new file mode 100644
index 0000000..3813cd5
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/core/controller/BaseController.java
@@ -0,0 +1,202 @@
+package com.jcdm.common.core.controller;
+
+import java.beans.PropertyEditorSupport;
+import java.util.Date;
+import java.util.List;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.WebDataBinder;
+import org.springframework.web.bind.annotation.InitBinder;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import com.jcdm.common.constant.HttpStatus;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.core.domain.model.LoginUser;
+import com.jcdm.common.core.page.PageDomain;
+import com.jcdm.common.core.page.TableDataInfo;
+import com.jcdm.common.core.page.TableSupport;
+import com.jcdm.common.utils.DateUtils;
+import com.jcdm.common.utils.PageUtils;
+import com.jcdm.common.utils.SecurityUtils;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.common.utils.sql.SqlUtil;
+
+/**
+ * web灞傞�氱敤鏁版嵁澶勭悊
+ * 
+ * @author jc
+ */
+public class BaseController
+{
+    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+    /**
+     * 灏嗗墠鍙颁紶閫掕繃鏉ョ殑鏃ユ湡鏍煎紡鐨勫瓧绗︿覆锛岃嚜鍔ㄨ浆鍖栦负Date绫诲瀷
+     */
+    @InitBinder
+    public void initBinder(WebDataBinder binder)
+    {
+        // Date 绫诲瀷杞崲
+        binder.registerCustomEditor(Date.class, new PropertyEditorSupport()
+        {
+            @Override
+            public void setAsText(String text)
+            {
+                setValue(DateUtils.parseDate(text));
+            }
+        });
+    }
+
+    /**
+     * 璁剧疆璇锋眰鍒嗛〉鏁版嵁
+     */
+    protected void startPage()
+    {
+        PageUtils.startPage();
+    }
+
+    /**
+     * 璁剧疆璇锋眰鎺掑簭鏁版嵁
+     */
+    protected void startOrderBy()
+    {
+        PageDomain pageDomain = TableSupport.buildPageRequest();
+        if (StringUtils.isNotEmpty(pageDomain.getOrderBy()))
+        {
+            String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
+            PageHelper.orderBy(orderBy);
+        }
+    }
+
+    /**
+     * 娓呯悊鍒嗛〉鐨勭嚎绋嬪彉閲�
+     */
+    protected void clearPage()
+    {
+        PageUtils.clearPage();
+    }
+
+    /**
+     * 鍝嶅簲璇锋眰鍒嗛〉鏁版嵁
+     */
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    protected TableDataInfo getDataTable(List<?> list)
+    {
+        TableDataInfo rspData = new TableDataInfo();
+        rspData.setCode(HttpStatus.SUCCESS);
+        rspData.setMsg("鏌ヨ鎴愬姛");
+        rspData.setRows(list);
+        rspData.setTotal(new PageInfo(list).getTotal());
+        return rspData;
+    }
+
+    /**
+     * 杩斿洖鎴愬姛
+     */
+    public AjaxResult success()
+    {
+        return AjaxResult.success();
+    }
+
+    /**
+     * 杩斿洖澶辫触娑堟伅
+     */
+    public AjaxResult error()
+    {
+        return AjaxResult.error();
+    }
+
+    /**
+     * 杩斿洖鎴愬姛娑堟伅
+     */
+    public AjaxResult success(String message)
+    {
+        return AjaxResult.success(message);
+    }
+    
+    /**
+     * 杩斿洖鎴愬姛娑堟伅
+     */
+    public AjaxResult success(Object data)
+    {
+        return AjaxResult.success(data);
+    }
+
+    /**
+     * 杩斿洖澶辫触娑堟伅
+     */
+    public AjaxResult error(String message)
+    {
+        return AjaxResult.error(message);
+    }
+
+    /**
+     * 杩斿洖璀﹀憡娑堟伅
+     */
+    public AjaxResult warn(String message)
+    {
+        return AjaxResult.warn(message);
+    }
+
+    /**
+     * 鍝嶅簲杩斿洖缁撴灉
+     * 
+     * @param rows 褰卞搷琛屾暟
+     * @return 鎿嶄綔缁撴灉
+     */
+    protected AjaxResult toAjax(int rows)
+    {
+        return rows > 0 ? AjaxResult.success() : AjaxResult.error();
+    }
+
+    /**
+     * 鍝嶅簲杩斿洖缁撴灉
+     * 
+     * @param result 缁撴灉
+     * @return 鎿嶄綔缁撴灉
+     */
+    protected AjaxResult toAjax(boolean result)
+    {
+        return result ? success() : error();
+    }
+
+    /**
+     * 椤甸潰璺宠浆
+     */
+    public String redirect(String url)
+    {
+        return StringUtils.format("redirect:{}", url);
+    }
+
+    /**
+     * 鑾峰彇鐢ㄦ埛缂撳瓨淇℃伅
+     */
+    public LoginUser getLoginUser()
+    {
+        return SecurityUtils.getLoginUser();
+    }
+
+    /**
+     * 鑾峰彇鐧诲綍鐢ㄦ埛id
+     */
+    public Long getUserId()
+    {
+        return getLoginUser().getUserId();
+    }
+
+    /**
+     * 鑾峰彇鐧诲綍閮ㄩ棬id
+     */
+    public Long getDeptId()
+    {
+        return getLoginUser().getDeptId();
+    }
+
+    /**
+     * 鑾峰彇鐧诲綍鐢ㄦ埛鍚�
+     */
+    public String getUsername()
+    {
+        return getLoginUser().getUsername();
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/core/domain/AjaxResult.java b/jcdm-common/src/main/java/com/jcdm/common/core/domain/AjaxResult.java
new file mode 100644
index 0000000..3f6ba0d
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/core/domain/AjaxResult.java
@@ -0,0 +1,216 @@
+package com.jcdm.common.core.domain;
+
+import java.util.HashMap;
+import java.util.Objects;
+import com.jcdm.common.constant.HttpStatus;
+import com.jcdm.common.utils.StringUtils;
+
+/**
+ * 鎿嶄綔娑堟伅鎻愰啋
+ * 
+ * @author jc
+ */
+public class AjaxResult extends HashMap<String, Object>
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 鐘舵�佺爜 */
+    public static final String CODE_TAG = "code";
+
+    /** 杩斿洖鍐呭 */
+    public static final String MSG_TAG = "msg";
+
+    /** 鏁版嵁瀵硅薄 */
+    public static final String DATA_TAG = "data";
+
+    /**
+     * 鍒濆鍖栦竴涓柊鍒涘缓鐨� AjaxResult 瀵硅薄锛屼娇鍏惰〃绀轰竴涓┖娑堟伅銆�
+     */
+    public AjaxResult()
+    {
+    }
+
+    /**
+     * 鍒濆鍖栦竴涓柊鍒涘缓鐨� AjaxResult 瀵硅薄
+     * 
+     * @param code 鐘舵�佺爜
+     * @param msg 杩斿洖鍐呭
+     */
+    public AjaxResult(int code, String msg)
+    {
+        super.put(CODE_TAG, code);
+        super.put(MSG_TAG, msg);
+    }
+
+    /**
+     * 鍒濆鍖栦竴涓柊鍒涘缓鐨� AjaxResult 瀵硅薄
+     * 
+     * @param code 鐘舵�佺爜
+     * @param msg 杩斿洖鍐呭
+     * @param data 鏁版嵁瀵硅薄
+     */
+    public AjaxResult(int code, String msg, Object data)
+    {
+        super.put(CODE_TAG, code);
+        super.put(MSG_TAG, msg);
+        if (StringUtils.isNotNull(data))
+        {
+            super.put(DATA_TAG, data);
+        }
+    }
+
+    /**
+     * 杩斿洖鎴愬姛娑堟伅
+     * 
+     * @return 鎴愬姛娑堟伅
+     */
+    public static AjaxResult success()
+    {
+        return AjaxResult.success("鎿嶄綔鎴愬姛");
+    }
+
+    /**
+     * 杩斿洖鎴愬姛鏁版嵁
+     * 
+     * @return 鎴愬姛娑堟伅
+     */
+    public static AjaxResult success(Object data)
+    {
+        return AjaxResult.success("鎿嶄綔鎴愬姛", data);
+    }
+
+    /**
+     * 杩斿洖鎴愬姛娑堟伅
+     * 
+     * @param msg 杩斿洖鍐呭
+     * @return 鎴愬姛娑堟伅
+     */
+    public static AjaxResult success(String msg)
+    {
+        return AjaxResult.success(msg, null);
+    }
+
+    /**
+     * 杩斿洖鎴愬姛娑堟伅
+     * 
+     * @param msg 杩斿洖鍐呭
+     * @param data 鏁版嵁瀵硅薄
+     * @return 鎴愬姛娑堟伅
+     */
+    public static AjaxResult success(String msg, Object data)
+    {
+        return new AjaxResult(HttpStatus.SUCCESS, msg, data);
+    }
+
+    /**
+     * 杩斿洖璀﹀憡娑堟伅
+     *
+     * @param msg 杩斿洖鍐呭
+     * @return 璀﹀憡娑堟伅
+     */
+    public static AjaxResult warn(String msg)
+    {
+        return AjaxResult.warn(msg, null);
+    }
+
+    /**
+     * 杩斿洖璀﹀憡娑堟伅
+     *
+     * @param msg 杩斿洖鍐呭
+     * @param data 鏁版嵁瀵硅薄
+     * @return 璀﹀憡娑堟伅
+     */
+    public static AjaxResult warn(String msg, Object data)
+    {
+        return new AjaxResult(HttpStatus.WARN, msg, data);
+    }
+
+    /**
+     * 杩斿洖閿欒娑堟伅
+     * 
+     * @return 閿欒娑堟伅
+     */
+    public static AjaxResult error()
+    {
+        return AjaxResult.error("鎿嶄綔澶辫触");
+    }
+
+    /**
+     * 杩斿洖閿欒娑堟伅
+     * 
+     * @param msg 杩斿洖鍐呭
+     * @return 閿欒娑堟伅
+     */
+    public static AjaxResult error(String msg)
+    {
+        return AjaxResult.error(msg, null);
+    }
+
+    /**
+     * 杩斿洖閿欒娑堟伅
+     * 
+     * @param msg 杩斿洖鍐呭
+     * @param data 鏁版嵁瀵硅薄
+     * @return 閿欒娑堟伅
+     */
+    public static AjaxResult error(String msg, Object data)
+    {
+        return new AjaxResult(HttpStatus.ERROR, msg, data);
+    }
+
+    /**
+     * 杩斿洖閿欒娑堟伅
+     * 
+     * @param code 鐘舵�佺爜
+     * @param msg 杩斿洖鍐呭
+     * @return 閿欒娑堟伅
+     */
+    public static AjaxResult error(int code, String msg)
+    {
+        return new AjaxResult(code, msg, null);
+    }
+
+    /**
+     * 鏄惁涓烘垚鍔熸秷鎭�
+     *
+     * @return 缁撴灉
+     */
+    public boolean isSuccess()
+    {
+        return Objects.equals(HttpStatus.SUCCESS, this.get(CODE_TAG));
+    }
+
+    /**
+     * 鏄惁涓鸿鍛婃秷鎭�
+     *
+     * @return 缁撴灉
+     */
+    public boolean isWarn()
+    {
+        return Objects.equals(HttpStatus.WARN, this.get(CODE_TAG));
+    }
+
+    /**
+     * 鏄惁涓洪敊璇秷鎭�
+     *
+     * @return 缁撴灉
+     */
+    public boolean isError()
+    {
+        return Objects.equals(HttpStatus.ERROR, this.get(CODE_TAG));
+    }
+
+    /**
+     * 鏂逛究閾惧紡璋冪敤
+     *
+     * @param key 閿�
+     * @param value 鍊�
+     * @return 鏁版嵁瀵硅薄
+     */
+    @Override
+    public AjaxResult put(String key, Object value)
+    {
+        super.put(key, value);
+        return this;
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/core/domain/BaseEntity.java b/jcdm-common/src/main/java/com/jcdm/common/core/domain/BaseEntity.java
new file mode 100644
index 0000000..298ec73
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/core/domain/BaseEntity.java
@@ -0,0 +1,118 @@
+package com.jcdm.common.core.domain;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+
+/**
+ * Entity鍩虹被
+ * 
+ * @author jc
+ */
+public class BaseEntity implements Serializable
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 鎼滅储鍊� */
+    @JsonIgnore
+    private String searchValue;
+
+    /** 鍒涘缓鑰� */
+    private String createBy;
+
+    /** 鍒涘缓鏃堕棿 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    /** 鏇存柊鑰� */
+    private String updateBy;
+
+    /** 鏇存柊鏃堕棿 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date updateTime;
+
+    /** 澶囨敞 */
+    private String remark;
+
+    /** 璇锋眰鍙傛暟 */
+    @JsonInclude(JsonInclude.Include.NON_EMPTY)
+    private Map<String, Object> params;
+
+    public String getSearchValue()
+    {
+        return searchValue;
+    }
+
+    public void setSearchValue(String searchValue)
+    {
+        this.searchValue = searchValue;
+    }
+
+    public String getCreateBy()
+    {
+        return createBy;
+    }
+
+    public void setCreateBy(String createBy)
+    {
+        this.createBy = createBy;
+    }
+
+    public Date getCreateTime()
+    {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime)
+    {
+        this.createTime = createTime;
+    }
+
+    public String getUpdateBy()
+    {
+        return updateBy;
+    }
+
+    public void setUpdateBy(String updateBy)
+    {
+        this.updateBy = updateBy;
+    }
+
+    public Date getUpdateTime()
+    {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Date updateTime)
+    {
+        this.updateTime = updateTime;
+    }
+
+    public String getRemark()
+    {
+        return remark;
+    }
+
+    public void setRemark(String remark)
+    {
+        this.remark = remark;
+    }
+
+    public Map<String, Object> getParams()
+    {
+        if (params == null)
+        {
+            params = new HashMap<>();
+        }
+        return params;
+    }
+
+    public void setParams(Map<String, Object> params)
+    {
+        this.params = params;
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/core/domain/R.java b/jcdm-common/src/main/java/com/jcdm/common/core/domain/R.java
new file mode 100644
index 0000000..318e4e6
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/core/domain/R.java
@@ -0,0 +1,115 @@
+package com.jcdm.common.core.domain;
+
+import java.io.Serializable;
+import com.jcdm.common.constant.HttpStatus;
+
+/**
+ * 鍝嶅簲淇℃伅涓讳綋
+ *
+ * @author jc
+ */
+public class R<T> implements Serializable
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 鎴愬姛 */
+    public static final int SUCCESS = HttpStatus.SUCCESS;
+
+    /** 澶辫触 */
+    public static final int FAIL = HttpStatus.ERROR;
+
+    private int code;
+
+    private String msg;
+
+    private T data;
+
+    public static <T> R<T> ok()
+    {
+        return restResult(null, SUCCESS, "鎿嶄綔鎴愬姛");
+    }
+
+    public static <T> R<T> ok(T data)
+    {
+        return restResult(data, SUCCESS, "鎿嶄綔鎴愬姛");
+    }
+
+    public static <T> R<T> ok(T data, String msg)
+    {
+        return restResult(data, SUCCESS, msg);
+    }
+
+    public static <T> R<T> fail()
+    {
+        return restResult(null, FAIL, "鎿嶄綔澶辫触");
+    }
+
+    public static <T> R<T> fail(String msg)
+    {
+        return restResult(null, FAIL, msg);
+    }
+
+    public static <T> R<T> fail(T data)
+    {
+        return restResult(data, FAIL, "鎿嶄綔澶辫触");
+    }
+
+    public static <T> R<T> fail(T data, String msg)
+    {
+        return restResult(data, FAIL, msg);
+    }
+
+    public static <T> R<T> fail(int code, String msg)
+    {
+        return restResult(null, code, msg);
+    }
+
+    private static <T> R<T> restResult(T data, int code, String msg)
+    {
+        R<T> apiResult = new R<>();
+        apiResult.setCode(code);
+        apiResult.setData(data);
+        apiResult.setMsg(msg);
+        return apiResult;
+    }
+
+    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 T getData()
+    {
+        return data;
+    }
+
+    public void setData(T data)
+    {
+        this.data = data;
+    }
+
+    public static <T> Boolean isError(R<T> ret)
+    {
+        return !isSuccess(ret);
+    }
+
+    public static <T> Boolean isSuccess(R<T> ret)
+    {
+        return R.SUCCESS == ret.getCode();
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/core/domain/TreeEntity.java b/jcdm-common/src/main/java/com/jcdm/common/core/domain/TreeEntity.java
new file mode 100644
index 0000000..dc4e995
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/core/domain/TreeEntity.java
@@ -0,0 +1,79 @@
+package com.jcdm.common.core.domain;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Tree鍩虹被
+ * 
+ * @author jc
+ */
+public class TreeEntity extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 鐖惰彍鍗曞悕绉� */
+    private String parentName;
+
+    /** 鐖惰彍鍗旾D */
+    private Long parentId;
+
+    /** 鏄剧ず椤哄簭 */
+    private Integer orderNum;
+
+    /** 绁栫骇鍒楄〃 */
+    private String ancestors;
+
+    /** 瀛愰儴闂� */
+    private List<?> children = new ArrayList<>();
+
+    public String getParentName()
+    {
+        return parentName;
+    }
+
+    public void setParentName(String parentName)
+    {
+        this.parentName = parentName;
+    }
+
+    public Long getParentId()
+    {
+        return parentId;
+    }
+
+    public void setParentId(Long parentId)
+    {
+        this.parentId = parentId;
+    }
+
+    public Integer getOrderNum()
+    {
+        return orderNum;
+    }
+
+    public void setOrderNum(Integer orderNum)
+    {
+        this.orderNum = orderNum;
+    }
+
+    public String getAncestors()
+    {
+        return ancestors;
+    }
+
+    public void setAncestors(String ancestors)
+    {
+        this.ancestors = ancestors;
+    }
+
+    public List<?> getChildren()
+    {
+        return children;
+    }
+
+    public void setChildren(List<?> children)
+    {
+        this.children = children;
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/core/domain/TreeSelect.java b/jcdm-common/src/main/java/com/jcdm/common/core/domain/TreeSelect.java
new file mode 100644
index 0000000..06b2e04
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/core/domain/TreeSelect.java
@@ -0,0 +1,77 @@
+package com.jcdm.common.core.domain;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.stream.Collectors;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.jcdm.common.core.domain.entity.SysDept;
+import com.jcdm.common.core.domain.entity.SysMenu;
+
+/**
+ * Treeselect鏍戠粨鏋勫疄浣撶被
+ * 
+ * @author jc
+ */
+public class TreeSelect implements Serializable
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 鑺傜偣ID */
+    private Long id;
+
+    /** 鑺傜偣鍚嶇О */
+    private String label;
+
+    /** 瀛愯妭鐐� */
+    @JsonInclude(JsonInclude.Include.NON_EMPTY)
+    private List<TreeSelect> children;
+
+    public TreeSelect()
+    {
+
+    }
+
+    public TreeSelect(SysDept dept)
+    {
+        this.id = dept.getDeptId();
+        this.label = dept.getDeptName();
+        this.children = dept.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
+    }
+
+    public TreeSelect(SysMenu menu)
+    {
+        this.id = menu.getMenuId();
+        this.label = menu.getMenuName();
+        this.children = menu.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
+    }
+
+    public Long getId()
+    {
+        return id;
+    }
+
+    public void setId(Long id)
+    {
+        this.id = id;
+    }
+
+    public String getLabel()
+    {
+        return label;
+    }
+
+    public void setLabel(String label)
+    {
+        this.label = label;
+    }
+
+    public List<TreeSelect> getChildren()
+    {
+        return children;
+    }
+
+    public void setChildren(List<TreeSelect> children)
+    {
+        this.children = children;
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysDept.java b/jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysDept.java
new file mode 100644
index 0000000..42965d3
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysDept.java
@@ -0,0 +1,203 @@
+package com.jcdm.common.core.domain.entity;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.validation.constraints.Email;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.jcdm.common.core.domain.BaseEntity;
+
+/**
+ * 閮ㄩ棬琛� sys_dept
+ * 
+ * @author jc
+ */
+public class SysDept extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 閮ㄩ棬ID */
+    private Long deptId;
+
+    /** 鐖堕儴闂↖D */
+    private Long parentId;
+
+    /** 绁栫骇鍒楄〃 */
+    private String ancestors;
+
+    /** 閮ㄩ棬鍚嶇О */
+    private String deptName;
+
+    /** 鏄剧ず椤哄簭 */
+    private Integer orderNum;
+
+    /** 璐熻矗浜� */
+    private String leader;
+
+    /** 鑱旂郴鐢佃瘽 */
+    private String phone;
+
+    /** 閭 */
+    private String email;
+
+    /** 閮ㄩ棬鐘舵��:0姝e父,1鍋滅敤 */
+    private String status;
+
+    /** 鍒犻櫎鏍囧織锛�0浠h〃瀛樺湪 2浠h〃鍒犻櫎锛� */
+    private String delFlag;
+
+    /** 鐖堕儴闂ㄥ悕绉� */
+    private String parentName;
+    
+    /** 瀛愰儴闂� */
+    private List<SysDept> children = new ArrayList<SysDept>();
+
+    public Long getDeptId()
+    {
+        return deptId;
+    }
+
+    public void setDeptId(Long deptId)
+    {
+        this.deptId = deptId;
+    }
+
+    public Long getParentId()
+    {
+        return parentId;
+    }
+
+    public void setParentId(Long parentId)
+    {
+        this.parentId = parentId;
+    }
+
+    public String getAncestors()
+    {
+        return ancestors;
+    }
+
+    public void setAncestors(String ancestors)
+    {
+        this.ancestors = ancestors;
+    }
+
+    @NotBlank(message = "閮ㄩ棬鍚嶇О涓嶈兘涓虹┖")
+    @Size(min = 0, max = 30, message = "閮ㄩ棬鍚嶇О闀垮害涓嶈兘瓒呰繃30涓瓧绗�")
+    public String getDeptName()
+    {
+        return deptName;
+    }
+
+    public void setDeptName(String deptName)
+    {
+        this.deptName = deptName;
+    }
+
+    @NotNull(message = "鏄剧ず椤哄簭涓嶈兘涓虹┖")
+    public Integer getOrderNum()
+    {
+        return orderNum;
+    }
+
+    public void setOrderNum(Integer orderNum)
+    {
+        this.orderNum = orderNum;
+    }
+
+    public String getLeader()
+    {
+        return leader;
+    }
+
+    public void setLeader(String leader)
+    {
+        this.leader = leader;
+    }
+
+    @Size(min = 0, max = 11, message = "鑱旂郴鐢佃瘽闀垮害涓嶈兘瓒呰繃11涓瓧绗�")
+    public String getPhone()
+    {
+        return phone;
+    }
+
+    public void setPhone(String phone)
+    {
+        this.phone = phone;
+    }
+
+    @Email(message = "閭鏍煎紡涓嶆纭�")
+    @Size(min = 0, max = 50, message = "閭闀垮害涓嶈兘瓒呰繃50涓瓧绗�")
+    public String getEmail()
+    {
+        return email;
+    }
+
+    public void setEmail(String email)
+    {
+        this.email = email;
+    }
+
+    public String getStatus()
+    {
+        return status;
+    }
+
+    public void setStatus(String status)
+    {
+        this.status = status;
+    }
+
+    public String getDelFlag()
+    {
+        return delFlag;
+    }
+
+    public void setDelFlag(String delFlag)
+    {
+        this.delFlag = delFlag;
+    }
+
+    public String getParentName()
+    {
+        return parentName;
+    }
+
+    public void setParentName(String parentName)
+    {
+        this.parentName = parentName;
+    }
+
+    public List<SysDept> getChildren()
+    {
+        return children;
+    }
+
+    public void setChildren(List<SysDept> children)
+    {
+        this.children = children;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("deptId", getDeptId())
+            .append("parentId", getParentId())
+            .append("ancestors", getAncestors())
+            .append("deptName", getDeptName())
+            .append("orderNum", getOrderNum())
+            .append("leader", getLeader())
+            .append("phone", getPhone())
+            .append("email", getEmail())
+            .append("status", getStatus())
+            .append("delFlag", getDelFlag())
+            .append("createBy", getCreateBy())
+            .append("createTime", getCreateTime())
+            .append("updateBy", getUpdateBy())
+            .append("updateTime", getUpdateTime())
+            .toString();
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysDictData.java b/jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysDictData.java
new file mode 100644
index 0000000..62079cc
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysDictData.java
@@ -0,0 +1,176 @@
+package com.jcdm.common.core.domain.entity;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Size;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.annotation.Excel.ColumnType;
+import com.jcdm.common.constant.UserConstants;
+import com.jcdm.common.core.domain.BaseEntity;
+
+/**
+ * 瀛楀吀鏁版嵁琛� sys_dict_data
+ * 
+ * @author jc
+ */
+public class SysDictData extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 瀛楀吀缂栫爜 */
+    @Excel(name = "瀛楀吀缂栫爜", cellType = ColumnType.NUMERIC)
+    private Long dictCode;
+
+    /** 瀛楀吀鎺掑簭 */
+    @Excel(name = "瀛楀吀鎺掑簭", cellType = ColumnType.NUMERIC)
+    private Long dictSort;
+
+    /** 瀛楀吀鏍囩 */
+    @Excel(name = "瀛楀吀鏍囩")
+    private String dictLabel;
+
+    /** 瀛楀吀閿�� */
+    @Excel(name = "瀛楀吀閿��")
+    private String dictValue;
+
+    /** 瀛楀吀绫诲瀷 */
+    @Excel(name = "瀛楀吀绫诲瀷")
+    private String dictType;
+
+    /** 鏍峰紡灞炴�э紙鍏朵粬鏍峰紡鎵╁睍锛� */
+    private String cssClass;
+
+    /** 琛ㄦ牸瀛楀吀鏍峰紡 */
+    private String listClass;
+
+    /** 鏄惁榛樿锛圷鏄� N鍚︼級 */
+    @Excel(name = "鏄惁榛樿", readConverterExp = "Y=鏄�,N=鍚�")
+    private String isDefault;
+
+    /** 鐘舵�侊紙0姝e父 1鍋滅敤锛� */
+    @Excel(name = "鐘舵��", readConverterExp = "0=姝e父,1=鍋滅敤")
+    private String status;
+
+    public Long getDictCode()
+    {
+        return dictCode;
+    }
+
+    public void setDictCode(Long dictCode)
+    {
+        this.dictCode = dictCode;
+    }
+
+    public Long getDictSort()
+    {
+        return dictSort;
+    }
+
+    public void setDictSort(Long dictSort)
+    {
+        this.dictSort = dictSort;
+    }
+
+    @NotBlank(message = "瀛楀吀鏍囩涓嶈兘涓虹┖")
+    @Size(min = 0, max = 100, message = "瀛楀吀鏍囩闀垮害涓嶈兘瓒呰繃100涓瓧绗�")
+    public String getDictLabel()
+    {
+        return dictLabel;
+    }
+
+    public void setDictLabel(String dictLabel)
+    {
+        this.dictLabel = dictLabel;
+    }
+
+    @NotBlank(message = "瀛楀吀閿�间笉鑳戒负绌�")
+    @Size(min = 0, max = 100, message = "瀛楀吀閿�奸暱搴︿笉鑳借秴杩�100涓瓧绗�")
+    public String getDictValue()
+    {
+        return dictValue;
+    }
+
+    public void setDictValue(String dictValue)
+    {
+        this.dictValue = dictValue;
+    }
+
+    @NotBlank(message = "瀛楀吀绫诲瀷涓嶈兘涓虹┖")
+    @Size(min = 0, max = 100, message = "瀛楀吀绫诲瀷闀垮害涓嶈兘瓒呰繃100涓瓧绗�")
+    public String getDictType()
+    {
+        return dictType;
+    }
+
+    public void setDictType(String dictType)
+    {
+        this.dictType = dictType;
+    }
+
+    @Size(min = 0, max = 100, message = "鏍峰紡灞炴�ч暱搴︿笉鑳借秴杩�100涓瓧绗�")
+    public String getCssClass()
+    {
+        return cssClass;
+    }
+
+    public void setCssClass(String cssClass)
+    {
+        this.cssClass = cssClass;
+    }
+
+    public String getListClass()
+    {
+        return listClass;
+    }
+
+    public void setListClass(String listClass)
+    {
+        this.listClass = listClass;
+    }
+
+    public boolean getDefault()
+    {
+        return UserConstants.YES.equals(this.isDefault);
+    }
+
+    public String getIsDefault()
+    {
+        return isDefault;
+    }
+
+    public void setIsDefault(String isDefault)
+    {
+        this.isDefault = isDefault;
+    }
+
+    public String getStatus()
+    {
+        return status;
+    }
+
+    public void setStatus(String status)
+    {
+        this.status = status;
+    }
+    
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("dictCode", getDictCode())
+            .append("dictSort", getDictSort())
+            .append("dictLabel", getDictLabel())
+            .append("dictValue", getDictValue())
+            .append("dictType", getDictType())
+            .append("cssClass", getCssClass())
+            .append("listClass", getListClass())
+            .append("isDefault", getIsDefault())
+            .append("status", getStatus())
+            .append("createBy", getCreateBy())
+            .append("createTime", getCreateTime())
+            .append("updateBy", getUpdateBy())
+            .append("updateTime", getUpdateTime())
+            .append("remark", getRemark())
+            .toString();
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysDictType.java b/jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysDictType.java
new file mode 100644
index 0000000..533ba22
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysDictType.java
@@ -0,0 +1,96 @@
+package com.jcdm.common.core.domain.entity;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Pattern;
+import javax.validation.constraints.Size;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.annotation.Excel.ColumnType;
+import com.jcdm.common.core.domain.BaseEntity;
+
+/**
+ * 瀛楀吀绫诲瀷琛� sys_dict_type
+ * 
+ * @author jc
+ */
+public class SysDictType extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 瀛楀吀涓婚敭 */
+    @Excel(name = "瀛楀吀涓婚敭", cellType = ColumnType.NUMERIC)
+    private Long dictId;
+
+    /** 瀛楀吀鍚嶇О */
+    @Excel(name = "瀛楀吀鍚嶇О")
+    private String dictName;
+
+    /** 瀛楀吀绫诲瀷 */
+    @Excel(name = "瀛楀吀绫诲瀷")
+    private String dictType;
+
+    /** 鐘舵�侊紙0姝e父 1鍋滅敤锛� */
+    @Excel(name = "鐘舵��", readConverterExp = "0=姝e父,1=鍋滅敤")
+    private String status;
+
+    public Long getDictId()
+    {
+        return dictId;
+    }
+
+    public void setDictId(Long dictId)
+    {
+        this.dictId = dictId;
+    }
+
+    @NotBlank(message = "瀛楀吀鍚嶇О涓嶈兘涓虹┖")
+    @Size(min = 0, max = 100, message = "瀛楀吀绫诲瀷鍚嶇О闀垮害涓嶈兘瓒呰繃100涓瓧绗�")
+    public String getDictName()
+    {
+        return dictName;
+    }
+
+    public void setDictName(String dictName)
+    {
+        this.dictName = dictName;
+    }
+
+    @NotBlank(message = "瀛楀吀绫诲瀷涓嶈兘涓虹┖")
+    @Size(min = 0, max = 100, message = "瀛楀吀绫诲瀷绫诲瀷闀垮害涓嶈兘瓒呰繃100涓瓧绗�")
+    @Pattern(regexp = "^[a-z][a-z0-9_]*$", message = "瀛楀吀绫诲瀷蹇呴』浠ュ瓧姣嶅紑澶达紝涓斿彧鑳戒负锛堝皬鍐欏瓧姣嶏紝鏁板瓧锛屼笅婊戠嚎锛�")
+    public String getDictType()
+    {
+        return dictType;
+    }
+
+    public void setDictType(String dictType)
+    {
+        this.dictType = dictType;
+    }
+
+    public String getStatus()
+    {
+        return status;
+    }
+
+    public void setStatus(String status)
+    {
+        this.status = status;
+    }
+    
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("dictId", getDictId())
+            .append("dictName", getDictName())
+            .append("dictType", getDictType())
+            .append("status", getStatus())
+            .append("createBy", getCreateBy())
+            .append("createTime", getCreateTime())
+            .append("updateBy", getUpdateBy())
+            .append("updateTime", getUpdateTime())
+            .append("remark", getRemark())
+            .toString();
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysMenu.java b/jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysMenu.java
new file mode 100644
index 0000000..33b8773
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysMenu.java
@@ -0,0 +1,259 @@
+package com.jcdm.common.core.domain.entity;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.jcdm.common.core.domain.BaseEntity;
+
+/**
+ * 鑿滃崟鏉冮檺琛� sys_menu
+ * 
+ * @author jc
+ */
+public class SysMenu extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 鑿滃崟ID */
+    private Long menuId;
+
+    /** 鑿滃崟鍚嶇О */
+    private String menuName;
+
+    /** 鐖惰彍鍗曞悕绉� */
+    private String parentName;
+
+    /** 鐖惰彍鍗旾D */
+    private Long parentId;
+
+    /** 鏄剧ず椤哄簭 */
+    private Integer orderNum;
+
+    /** 璺敱鍦板潃 */
+    private String path;
+
+    /** 缁勪欢璺緞 */
+    private String component;
+
+    /** 璺敱鍙傛暟 */
+    private String query;
+
+    /** 鏄惁涓哄閾撅紙0鏄� 1鍚︼級 */
+    private String isFrame;
+
+    /** 鏄惁缂撳瓨锛�0缂撳瓨 1涓嶇紦瀛橈級 */
+    private String isCache;
+
+    /** 绫诲瀷锛圡鐩綍 C鑿滃崟 F鎸夐挳锛� */
+    private String menuType;
+
+    /** 鏄剧ず鐘舵�侊紙0鏄剧ず 1闅愯棌锛� */
+    private String visible;
+    
+    /** 鑿滃崟鐘舵�侊紙0姝e父 1鍋滅敤锛� */
+    private String status;
+
+    /** 鏉冮檺瀛楃涓� */
+    private String perms;
+
+    /** 鑿滃崟鍥炬爣 */
+    private String icon;
+
+    /** 瀛愯彍鍗� */
+    private List<SysMenu> children = new ArrayList<SysMenu>();
+
+    public Long getMenuId()
+    {
+        return menuId;
+    }
+
+    public void setMenuId(Long menuId)
+    {
+        this.menuId = menuId;
+    }
+
+    @NotBlank(message = "鑿滃崟鍚嶇О涓嶈兘涓虹┖")
+    @Size(min = 0, max = 50, message = "鑿滃崟鍚嶇О闀垮害涓嶈兘瓒呰繃50涓瓧绗�")
+    public String getMenuName()
+    {
+        return menuName;
+    }
+
+    public void setMenuName(String menuName)
+    {
+        this.menuName = menuName;
+    }
+
+    public String getParentName()
+    {
+        return parentName;
+    }
+
+    public void setParentName(String parentName)
+    {
+        this.parentName = parentName;
+    }
+
+    public Long getParentId()
+    {
+        return parentId;
+    }
+
+    public void setParentId(Long parentId)
+    {
+        this.parentId = parentId;
+    }
+
+    @NotNull(message = "鏄剧ず椤哄簭涓嶈兘涓虹┖")
+    public Integer getOrderNum()
+    {
+        return orderNum;
+    }
+
+    public void setOrderNum(Integer orderNum)
+    {
+        this.orderNum = orderNum;
+    }
+
+    @Size(min = 0, max = 200, message = "璺敱鍦板潃涓嶈兘瓒呰繃200涓瓧绗�")
+    public String getPath()
+    {
+        return path;
+    }
+
+    public void setPath(String path)
+    {
+        this.path = path;
+    }
+
+    @Size(min = 0, max = 200, message = "缁勪欢璺緞涓嶈兘瓒呰繃255涓瓧绗�")
+    public String getComponent()
+    {
+        return component;
+    }
+
+    public void setComponent(String component)
+    {
+        this.component = component;
+    }
+
+    public String getQuery()
+    {
+        return query;
+    }
+
+    public void setQuery(String query)
+    {
+        this.query = query;
+    }
+
+    public String getIsFrame()
+    {
+        return isFrame;
+    }
+
+    public void setIsFrame(String isFrame)
+    {
+        this.isFrame = isFrame;
+    }
+
+    public String getIsCache()
+    {
+        return isCache;
+    }
+
+    public void setIsCache(String isCache)
+    {
+        this.isCache = isCache;
+    }
+
+    @NotBlank(message = "鑿滃崟绫诲瀷涓嶈兘涓虹┖")
+    public String getMenuType()
+    {
+        return menuType;
+    }
+
+    public void setMenuType(String menuType)
+    {
+        this.menuType = menuType;
+    }
+
+    public String getVisible()
+    {
+        return visible;
+    }
+
+    public void setVisible(String visible)
+    {
+        this.visible = visible;
+    }
+
+    public String getStatus()
+    {
+        return status;
+    }
+
+    public void setStatus(String status)
+    {
+        this.status = status;
+    }
+
+    @Size(min = 0, max = 100, message = "鏉冮檺鏍囪瘑闀垮害涓嶈兘瓒呰繃100涓瓧绗�")
+    public String getPerms()
+    {
+        return perms;
+    }
+
+    public void setPerms(String perms)
+    {
+        this.perms = perms;
+    }
+
+    public String getIcon()
+    {
+        return icon;
+    }
+
+    public void setIcon(String icon)
+    {
+        this.icon = icon;
+    }
+
+    public List<SysMenu> getChildren()
+    {
+        return children;
+    }
+
+    public void setChildren(List<SysMenu> children)
+    {
+        this.children = children;
+    }
+    
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("menuId", getMenuId())
+            .append("menuName", getMenuName())
+            .append("parentId", getParentId())
+            .append("orderNum", getOrderNum())
+            .append("path", getPath())
+            .append("component", getComponent())
+            .append("isFrame", getIsFrame())
+            .append("IsCache", getIsCache())
+            .append("menuType", getMenuType())
+            .append("visible", getVisible())
+            .append("status ", getStatus())
+            .append("perms", getPerms())
+            .append("icon", getIcon())
+            .append("createBy", getCreateBy())
+            .append("createTime", getCreateTime())
+            .append("updateBy", getUpdateBy())
+            .append("updateTime", getUpdateTime())
+            .append("remark", getRemark())
+            .toString();
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysRole.java b/jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysRole.java
new file mode 100644
index 0000000..261360a
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysRole.java
@@ -0,0 +1,241 @@
+package com.jcdm.common.core.domain.entity;
+
+import java.util.Set;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.annotation.Excel.ColumnType;
+import com.jcdm.common.core.domain.BaseEntity;
+
+/**
+ * 瑙掕壊琛� sys_role
+ * 
+ * @author jc
+ */
+public class SysRole extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 瑙掕壊ID */
+    @Excel(name = "瑙掕壊搴忓彿", cellType = ColumnType.NUMERIC)
+    private Long roleId;
+
+    /** 瑙掕壊鍚嶇О */
+    @Excel(name = "瑙掕壊鍚嶇О")
+    private String roleName;
+
+    /** 瑙掕壊鏉冮檺 */
+    @Excel(name = "瑙掕壊鏉冮檺")
+    private String roleKey;
+
+    /** 瑙掕壊鎺掑簭 */
+    @Excel(name = "瑙掕壊鎺掑簭")
+    private Integer roleSort;
+
+    /** 鏁版嵁鑼冨洿锛�1锛氭墍鏈夋暟鎹潈闄愶紱2锛氳嚜瀹氫箟鏁版嵁鏉冮檺锛�3锛氭湰閮ㄩ棬鏁版嵁鏉冮檺锛�4锛氭湰閮ㄩ棬鍙婁互涓嬫暟鎹潈闄愶紱5锛氫粎鏈汉鏁版嵁鏉冮檺锛� */
+    @Excel(name = "鏁版嵁鑼冨洿", readConverterExp = "1=鎵�鏈夋暟鎹潈闄�,2=鑷畾涔夋暟鎹潈闄�,3=鏈儴闂ㄦ暟鎹潈闄�,4=鏈儴闂ㄥ強浠ヤ笅鏁版嵁鏉冮檺,5=浠呮湰浜烘暟鎹潈闄�")
+    private String dataScope;
+
+    /** 鑿滃崟鏍戦�夋嫨椤规槸鍚﹀叧鑱旀樉绀猴紙 0锛氱埗瀛愪笉浜掔浉鍏宠仈鏄剧ず 1锛氱埗瀛愪簰鐩稿叧鑱旀樉绀猴級 */
+    private boolean menuCheckStrictly;
+
+    /** 閮ㄩ棬鏍戦�夋嫨椤规槸鍚﹀叧鑱旀樉绀猴紙0锛氱埗瀛愪笉浜掔浉鍏宠仈鏄剧ず 1锛氱埗瀛愪簰鐩稿叧鑱旀樉绀� 锛� */
+    private boolean deptCheckStrictly;
+
+    /** 瑙掕壊鐘舵�侊紙0姝e父 1鍋滅敤锛� */
+    @Excel(name = "瑙掕壊鐘舵��", readConverterExp = "0=姝e父,1=鍋滅敤")
+    private String status;
+
+    /** 鍒犻櫎鏍囧織锛�0浠h〃瀛樺湪 2浠h〃鍒犻櫎锛� */
+    private String delFlag;
+
+    /** 鐢ㄦ埛鏄惁瀛樺湪姝よ鑹叉爣璇� 榛樿涓嶅瓨鍦� */
+    private boolean flag = false;
+
+    /** 鑿滃崟缁� */
+    private Long[] menuIds;
+
+    /** 閮ㄩ棬缁勶紙鏁版嵁鏉冮檺锛� */
+    private Long[] deptIds;
+
+    /** 瑙掕壊鑿滃崟鏉冮檺 */
+    private Set<String> permissions;
+
+    public SysRole()
+    {
+
+    }
+
+    public SysRole(Long roleId)
+    {
+        this.roleId = roleId;
+    }
+
+    public Long getRoleId()
+    {
+        return roleId;
+    }
+
+    public void setRoleId(Long roleId)
+    {
+        this.roleId = roleId;
+    }
+
+    public boolean isAdmin()
+    {
+        return isAdmin(this.roleId);
+    }
+
+    public static boolean isAdmin(Long roleId)
+    {
+        return roleId != null && 1L == roleId;
+    }
+
+    @NotBlank(message = "瑙掕壊鍚嶇О涓嶈兘涓虹┖")
+    @Size(min = 0, max = 30, message = "瑙掕壊鍚嶇О闀垮害涓嶈兘瓒呰繃30涓瓧绗�")
+    public String getRoleName()
+    {
+        return roleName;
+    }
+
+    public void setRoleName(String roleName)
+    {
+        this.roleName = roleName;
+    }
+
+    @NotBlank(message = "鏉冮檺瀛楃涓嶈兘涓虹┖")
+    @Size(min = 0, max = 100, message = "鏉冮檺瀛楃闀垮害涓嶈兘瓒呰繃100涓瓧绗�")
+    public String getRoleKey()
+    {
+        return roleKey;
+    }
+
+    public void setRoleKey(String roleKey)
+    {
+        this.roleKey = roleKey;
+    }
+
+    @NotNull(message = "鏄剧ず椤哄簭涓嶈兘涓虹┖")
+    public Integer getRoleSort()
+    {
+        return roleSort;
+    }
+
+    public void setRoleSort(Integer roleSort)
+    {
+        this.roleSort = roleSort;
+    }
+
+    public String getDataScope()
+    {
+        return dataScope;
+    }
+
+    public void setDataScope(String dataScope)
+    {
+        this.dataScope = dataScope;
+    }
+
+    public boolean isMenuCheckStrictly()
+    {
+        return menuCheckStrictly;
+    }
+
+    public void setMenuCheckStrictly(boolean menuCheckStrictly)
+    {
+        this.menuCheckStrictly = menuCheckStrictly;
+    }
+
+    public boolean isDeptCheckStrictly()
+    {
+        return deptCheckStrictly;
+    }
+
+    public void setDeptCheckStrictly(boolean deptCheckStrictly)
+    {
+        this.deptCheckStrictly = deptCheckStrictly;
+    }
+
+    public String getStatus()
+    {
+        return status;
+    }
+
+    public void setStatus(String status)
+    {
+        this.status = status;
+    }
+
+    public String getDelFlag()
+    {
+        return delFlag;
+    }
+
+    public void setDelFlag(String delFlag)
+    {
+        this.delFlag = delFlag;
+    }
+
+    public boolean isFlag()
+    {
+        return flag;
+    }
+
+    public void setFlag(boolean flag)
+    {
+        this.flag = flag;
+    }
+
+    public Long[] getMenuIds()
+    {
+        return menuIds;
+    }
+
+    public void setMenuIds(Long[] menuIds)
+    {
+        this.menuIds = menuIds;
+    }
+
+    public Long[] getDeptIds()
+    {
+        return deptIds;
+    }
+
+    public void setDeptIds(Long[] deptIds)
+    {
+        this.deptIds = deptIds;
+    }
+
+    public Set<String> getPermissions()
+    {
+        return permissions;
+    }
+
+    public void setPermissions(Set<String> permissions)
+    {
+        this.permissions = permissions;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("roleId", getRoleId())
+            .append("roleName", getRoleName())
+            .append("roleKey", getRoleKey())
+            .append("roleSort", getRoleSort())
+            .append("dataScope", getDataScope())
+            .append("menuCheckStrictly", isMenuCheckStrictly())
+            .append("deptCheckStrictly", isDeptCheckStrictly())
+            .append("status", getStatus())
+            .append("delFlag", getDelFlag())
+            .append("createBy", getCreateBy())
+            .append("createTime", getCreateTime())
+            .append("updateBy", getUpdateBy())
+            .append("updateTime", getUpdateTime())
+            .append("remark", getRemark())
+            .toString();
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysUser.java b/jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysUser.java
new file mode 100644
index 0000000..2a41c7d
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysUser.java
@@ -0,0 +1,324 @@
+package com.jcdm.common.core.domain.entity;
+
+import java.util.Date;
+import java.util.List;
+import javax.validation.constraints.*;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.annotation.Excel.ColumnType;
+import com.jcdm.common.annotation.Excel.Type;
+import com.jcdm.common.annotation.Excels;
+import com.jcdm.common.core.domain.BaseEntity;
+import com.jcdm.common.xss.Xss;
+
+/**
+ * 鐢ㄦ埛瀵硅薄 sys_user
+ * 
+ * @author jc
+ */
+public class SysUser extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 鐢ㄦ埛ID */
+    @Excel(name = "鐢ㄦ埛搴忓彿", cellType = ColumnType.NUMERIC, prompt = "鐢ㄦ埛缂栧彿")
+    private Long userId;
+
+    /** 閮ㄩ棬ID */
+    @Excel(name = "閮ㄩ棬缂栧彿", type = Type.IMPORT)
+    private Long deptId;
+
+    /** 鐢ㄦ埛璐﹀彿 */
+    @Excel(name = "鐧诲綍鍚嶇О")
+    private String userName;
+
+    /** 鐢ㄦ埛鏄电О */
+    @Excel(name = "鐢ㄦ埛鍚嶇О")
+    private String nickName;
+
+    /** 鐢ㄦ埛閭 */
+    @Excel(name = "鐢ㄦ埛閭")
+    private String email;
+
+    /** 鎵嬫満鍙风爜 */
+    @Excel(name = "鎵嬫満鍙风爜")
+    private String phonenumber;
+
+    /** 鐢ㄦ埛鎬у埆 */
+    @Excel(name = "鐢ㄦ埛鎬у埆", readConverterExp = "0=鐢�,1=濂�,2=鏈煡")
+    private String sex;
+
+    /** 鐢ㄦ埛澶村儚 */
+    private String avatar;
+
+    /** 瀵嗙爜 */
+    private String password;
+
+    /** 甯愬彿鐘舵�侊紙0姝e父 1鍋滅敤锛� */
+    @Excel(name = "甯愬彿鐘舵��", readConverterExp = "0=姝e父,1=鍋滅敤")
+    private String status;
+
+    /** 鍒犻櫎鏍囧織锛�0浠h〃瀛樺湪 2浠h〃鍒犻櫎锛� */
+    private String delFlag;
+
+    /** 鏈�鍚庣櫥褰旾P */
+    @Excel(name = "鏈�鍚庣櫥褰旾P", type = Type.EXPORT)
+    private String loginIp;
+
+    /** 鏈�鍚庣櫥褰曟椂闂� */
+    @Excel(name = "鏈�鍚庣櫥褰曟椂闂�", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT)
+    private Date loginDate;
+
+    /** 閮ㄩ棬瀵硅薄 */
+    @Excels({
+        @Excel(name = "閮ㄩ棬鍚嶇О", targetAttr = "deptName", type = Type.EXPORT),
+        @Excel(name = "閮ㄩ棬璐熻矗浜�", targetAttr = "leader", type = Type.EXPORT)
+    })
+    private SysDept dept;
+
+    /** 瑙掕壊瀵硅薄 */
+    private List<SysRole> roles;
+
+    /** 瑙掕壊缁� */
+    private Long[] roleIds;
+
+    /** 宀椾綅缁� */
+    private Long[] postIds;
+
+    /** 瑙掕壊ID */
+    private Long roleId;
+
+    public SysUser()
+    {
+
+    }
+
+    public SysUser(Long userId)
+    {
+        this.userId = userId;
+    }
+
+    public Long getUserId()
+    {
+        return userId;
+    }
+
+    public void setUserId(Long userId)
+    {
+        this.userId = userId;
+    }
+
+    public boolean isAdmin()
+    {
+        return isAdmin(this.userId);
+    }
+
+    public static boolean isAdmin(Long userId)
+    {
+        return userId != null && 1L == userId;
+    }
+
+    public Long getDeptId()
+    {
+        return deptId;
+    }
+
+    public void setDeptId(Long deptId)
+    {
+        this.deptId = deptId;
+    }
+
+    @Xss(message = "鐢ㄦ埛鏄电О涓嶈兘鍖呭惈鑴氭湰瀛楃")
+    @Size(min = 0, max = 30, message = "鐢ㄦ埛鏄电О闀垮害涓嶈兘瓒呰繃30涓瓧绗�")
+    public String getNickName()
+    {
+        return nickName;
+    }
+
+    public void setNickName(String nickName)
+    {
+        this.nickName = nickName;
+    }
+
+    @Xss(message = "鐢ㄦ埛璐﹀彿涓嶈兘鍖呭惈鑴氭湰瀛楃")
+    @NotBlank(message = "鐢ㄦ埛璐﹀彿涓嶈兘涓虹┖")
+    @Size(min = 0, max = 30, message = "鐢ㄦ埛璐﹀彿闀垮害涓嶈兘瓒呰繃30涓瓧绗�")
+    public String getUserName()
+    {
+        return userName;
+    }
+
+    public void setUserName(String userName)
+    {
+        this.userName = userName;
+    }
+
+    @Email(message = "閭鏍煎紡涓嶆纭�")
+    @Size(min = 0, max = 50, message = "閭闀垮害涓嶈兘瓒呰繃50涓瓧绗�")
+    public String getEmail()
+    {
+        return email;
+    }
+
+    public void setEmail(String email)
+    {
+        this.email = email;
+    }
+
+    @Size(min = 0, max = 11, message = "鎵嬫満鍙风爜闀垮害涓嶈兘瓒呰繃11涓瓧绗�")
+    public String getPhonenumber()
+    {
+        return phonenumber;
+    }
+
+    public void setPhonenumber(String phonenumber)
+    {
+        this.phonenumber = phonenumber;
+    }
+
+    public String getSex()
+    {
+        return sex;
+    }
+
+    public void setSex(String sex)
+    {
+        this.sex = sex;
+    }
+
+    public String getAvatar()
+    {
+        return avatar;
+    }
+
+    public void setAvatar(String avatar)
+    {
+        this.avatar = avatar;
+    }
+
+    public String getPassword()
+    {
+        return password;
+    }
+
+    public void setPassword(String password)
+    {
+        this.password = password;
+    }
+
+    public String getStatus()
+    {
+        return status;
+    }
+
+    public void setStatus(String status)
+    {
+        this.status = status;
+    }
+
+    public String getDelFlag()
+    {
+        return delFlag;
+    }
+
+    public void setDelFlag(String delFlag)
+    {
+        this.delFlag = delFlag;
+    }
+
+    public String getLoginIp()
+    {
+        return loginIp;
+    }
+
+    public void setLoginIp(String loginIp)
+    {
+        this.loginIp = loginIp;
+    }
+
+    public Date getLoginDate()
+    {
+        return loginDate;
+    }
+
+    public void setLoginDate(Date loginDate)
+    {
+        this.loginDate = loginDate;
+    }
+
+    public SysDept getDept()
+    {
+        return dept;
+    }
+
+    public void setDept(SysDept dept)
+    {
+        this.dept = dept;
+    }
+
+    public List<SysRole> getRoles()
+    {
+        return roles;
+    }
+
+    public void setRoles(List<SysRole> roles)
+    {
+        this.roles = roles;
+    }
+
+    public Long[] getRoleIds()
+    {
+        return roleIds;
+    }
+
+    public void setRoleIds(Long[] roleIds)
+    {
+        this.roleIds = roleIds;
+    }
+
+    public Long[] getPostIds()
+    {
+        return postIds;
+    }
+
+    public void setPostIds(Long[] postIds)
+    {
+        this.postIds = postIds;
+    }
+
+    public Long getRoleId()
+    {
+        return roleId;
+    }
+
+    public void setRoleId(Long roleId)
+    {
+        this.roleId = roleId;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("userId", getUserId())
+            .append("deptId", getDeptId())
+            .append("userName", getUserName())
+            .append("nickName", getNickName())
+            .append("email", getEmail())
+            .append("phonenumber", getPhonenumber())
+            .append("sex", getSex())
+            .append("avatar", getAvatar())
+            .append("password", getPassword())
+            .append("status", getStatus())
+            .append("delFlag", getDelFlag())
+            .append("loginIp", getLoginIp())
+            .append("loginDate", getLoginDate())
+            .append("createBy", getCreateBy())
+            .append("createTime", getCreateTime())
+            .append("updateBy", getUpdateBy())
+            .append("updateTime", getUpdateTime())
+            .append("remark", getRemark())
+            .append("dept", getDept())
+            .toString();
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/core/domain/model/LoginBody.java b/jcdm-common/src/main/java/com/jcdm/common/core/domain/model/LoginBody.java
new file mode 100644
index 0000000..4c2fd11
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/core/domain/model/LoginBody.java
@@ -0,0 +1,69 @@
+package com.jcdm.common.core.domain.model;
+
+/**
+ * 鐢ㄦ埛鐧诲綍瀵硅薄
+ * 
+ * @author jc
+ */
+public class LoginBody
+{
+    /**
+     * 鐢ㄦ埛鍚�
+     */
+    private String username;
+
+    /**
+     * 鐢ㄦ埛瀵嗙爜
+     */
+    private String password;
+
+    /**
+     * 楠岃瘉鐮�
+     */
+    private String code;
+
+    /**
+     * 鍞竴鏍囪瘑
+     */
+    private String uuid;
+
+    public String getUsername()
+    {
+        return username;
+    }
+
+    public void setUsername(String username)
+    {
+        this.username = username;
+    }
+
+    public String getPassword()
+    {
+        return password;
+    }
+
+    public void setPassword(String password)
+    {
+        this.password = password;
+    }
+
+    public String getCode()
+    {
+        return code;
+    }
+
+    public void setCode(String code)
+    {
+        this.code = code;
+    }
+
+    public String getUuid()
+    {
+        return uuid;
+    }
+
+    public void setUuid(String uuid)
+    {
+        this.uuid = uuid;
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/core/domain/model/LoginUser.java b/jcdm-common/src/main/java/com/jcdm/common/core/domain/model/LoginUser.java
new file mode 100644
index 0000000..70ebb32
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/core/domain/model/LoginUser.java
@@ -0,0 +1,266 @@
+package com.jcdm.common.core.domain.model;
+
+import com.alibaba.fastjson2.annotation.JSONField;
+import com.jcdm.common.core.domain.entity.SysUser;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * 鐧诲綍鐢ㄦ埛韬唤鏉冮檺
+ * 
+ * @author jc
+ */
+public class LoginUser implements UserDetails
+{
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 鐢ㄦ埛ID
+     */
+    private Long userId;
+
+    /**
+     * 閮ㄩ棬ID
+     */
+    private Long deptId;
+
+    /**
+     * 鐢ㄦ埛鍞竴鏍囪瘑
+     */
+    private String token;
+
+    /**
+     * 鐧诲綍鏃堕棿
+     */
+    private Long loginTime;
+
+    /**
+     * 杩囨湡鏃堕棿
+     */
+    private Long expireTime;
+
+    /**
+     * 鐧诲綍IP鍦板潃
+     */
+    private String ipaddr;
+
+    /**
+     * 鐧诲綍鍦扮偣
+     */
+    private String loginLocation;
+
+    /**
+     * 娴忚鍣ㄧ被鍨�
+     */
+    private String browser;
+
+    /**
+     * 鎿嶄綔绯荤粺
+     */
+    private String os;
+
+    /**
+     * 鏉冮檺鍒楄〃
+     */
+    private Set<String> permissions;
+
+    /**
+     * 鐢ㄦ埛淇℃伅
+     */
+    private SysUser user;
+
+    public LoginUser()
+    {
+    }
+
+    public LoginUser(SysUser user, Set<String> permissions)
+    {
+        this.user = user;
+        this.permissions = permissions;
+    }
+
+    public LoginUser(Long userId, Long deptId, SysUser user, Set<String> permissions)
+    {
+        this.userId = userId;
+        this.deptId = deptId;
+        this.user = user;
+        this.permissions = permissions;
+    }
+
+    public Long getUserId()
+    {
+        return userId;
+    }
+
+    public void setUserId(Long userId)
+    {
+        this.userId = userId;
+    }
+
+    public Long getDeptId()
+    {
+        return deptId;
+    }
+
+    public void setDeptId(Long deptId)
+    {
+        this.deptId = deptId;
+    }
+
+    public String getToken()
+    {
+        return token;
+    }
+
+    public void setToken(String token)
+    {
+        this.token = token;
+    }
+
+    @JSONField(serialize = false)
+    @Override
+    public String getPassword()
+    {
+        return user.getPassword();
+    }
+
+    @Override
+    public String getUsername()
+    {
+        return user.getUserName();
+    }
+
+    /**
+     * 璐︽埛鏄惁鏈繃鏈�,杩囨湡鏃犳硶楠岃瘉
+     */
+    @JSONField(serialize = false)
+    @Override
+    public boolean isAccountNonExpired()
+    {
+        return true;
+    }
+
+    /**
+     * 鎸囧畾鐢ㄦ埛鏄惁瑙i攣,閿佸畾鐨勭敤鎴锋棤娉曡繘琛岃韩浠介獙璇�
+     * 
+     * @return
+     */
+    @JSONField(serialize = false)
+    @Override
+    public boolean isAccountNonLocked()
+    {
+        return true;
+    }
+
+    /**
+     * 鎸囩ず鏄惁宸茶繃鏈熺殑鐢ㄦ埛鐨勫嚟鎹�(瀵嗙爜),杩囨湡鐨勫嚟鎹槻姝㈣璇�
+     * 
+     * @return
+     */
+    @JSONField(serialize = false)
+    @Override
+    public boolean isCredentialsNonExpired()
+    {
+        return true;
+    }
+
+    /**
+     * 鏄惁鍙敤 ,绂佺敤鐨勭敤鎴蜂笉鑳借韩浠介獙璇�
+     * 
+     * @return
+     */
+    @JSONField(serialize = false)
+    @Override
+    public boolean isEnabled()
+    {
+        return true;
+    }
+
+    public Long getLoginTime()
+    {
+        return loginTime;
+    }
+
+    public void setLoginTime(Long loginTime)
+    {
+        this.loginTime = loginTime;
+    }
+
+    public String getIpaddr()
+    {
+        return ipaddr;
+    }
+
+    public void setIpaddr(String ipaddr)
+    {
+        this.ipaddr = ipaddr;
+    }
+
+    public String getLoginLocation()
+    {
+        return loginLocation;
+    }
+
+    public void setLoginLocation(String loginLocation)
+    {
+        this.loginLocation = loginLocation;
+    }
+
+    public String getBrowser()
+    {
+        return browser;
+    }
+
+    public void setBrowser(String browser)
+    {
+        this.browser = browser;
+    }
+
+    public String getOs()
+    {
+        return os;
+    }
+
+    public void setOs(String os)
+    {
+        this.os = os;
+    }
+
+    public Long getExpireTime()
+    {
+        return expireTime;
+    }
+
+    public void setExpireTime(Long expireTime)
+    {
+        this.expireTime = expireTime;
+    }
+
+    public Set<String> getPermissions()
+    {
+        return permissions;
+    }
+
+    public void setPermissions(Set<String> permissions)
+    {
+        this.permissions = permissions;
+    }
+
+    public SysUser getUser()
+    {
+        return user;
+    }
+
+    public void setUser(SysUser user)
+    {
+        this.user = user;
+    }
+
+    @Override
+    public Collection<? extends GrantedAuthority> getAuthorities()
+    {
+        return null;
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/core/domain/model/RegisterBody.java b/jcdm-common/src/main/java/com/jcdm/common/core/domain/model/RegisterBody.java
new file mode 100644
index 0000000..f494b06
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/core/domain/model/RegisterBody.java
@@ -0,0 +1,11 @@
+package com.jcdm.common.core.domain.model;
+
+/**
+ * 鐢ㄦ埛娉ㄥ唽瀵硅薄
+ * 
+ * @author jc
+ */
+public class RegisterBody extends LoginBody
+{
+
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/core/page/PageDomain.java b/jcdm-common/src/main/java/com/jcdm/common/core/page/PageDomain.java
new file mode 100644
index 0000000..a1e5520
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/core/page/PageDomain.java
@@ -0,0 +1,101 @@
+package com.jcdm.common.core.page;
+
+import com.jcdm.common.utils.StringUtils;
+
+/**
+ * 鍒嗛〉鏁版嵁
+ * 
+ * @author jc
+ */
+public class PageDomain
+{
+    /** 褰撳墠璁板綍璧峰绱㈠紩 */
+    private Integer pageNum;
+
+    /** 姣忛〉鏄剧ず璁板綍鏁� */
+    private Integer pageSize;
+
+    /** 鎺掑簭鍒� */
+    private String orderByColumn;
+
+    /** 鎺掑簭鐨勬柟鍚慸esc鎴栬�卆sc */
+    private String isAsc = "asc";
+
+    /** 鍒嗛〉鍙傛暟鍚堢悊鍖� */
+    private Boolean reasonable = true;
+
+    public String getOrderBy()
+    {
+        if (StringUtils.isEmpty(orderByColumn))
+        {
+            return "";
+        }
+        return StringUtils.toUnderScoreCase(orderByColumn) + " " + isAsc;
+    }
+
+    public Integer getPageNum()
+    {
+        return pageNum;
+    }
+
+    public void setPageNum(Integer pageNum)
+    {
+        this.pageNum = pageNum;
+    }
+
+    public Integer getPageSize()
+    {
+        return pageSize;
+    }
+
+    public void setPageSize(Integer pageSize)
+    {
+        this.pageSize = pageSize;
+    }
+
+    public String getOrderByColumn()
+    {
+        return orderByColumn;
+    }
+
+    public void setOrderByColumn(String orderByColumn)
+    {
+        this.orderByColumn = orderByColumn;
+    }
+
+    public String getIsAsc()
+    {
+        return isAsc;
+    }
+
+    public void setIsAsc(String isAsc)
+    {
+        if (StringUtils.isNotEmpty(isAsc))
+        {
+            // 鍏煎鍓嶇鎺掑簭绫诲瀷
+            if ("ascending".equals(isAsc))
+            {
+                isAsc = "asc";
+            }
+            else if ("descending".equals(isAsc))
+            {
+                isAsc = "desc";
+            }
+            this.isAsc = isAsc;
+        }
+    }
+
+    public Boolean getReasonable()
+    {
+        if (StringUtils.isNull(reasonable))
+        {
+            return Boolean.TRUE;
+        }
+        return reasonable;
+    }
+
+    public void setReasonable(Boolean reasonable)
+    {
+        this.reasonable = reasonable;
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/core/page/TableDataInfo.java b/jcdm-common/src/main/java/com/jcdm/common/core/page/TableDataInfo.java
new file mode 100644
index 0000000..6d56343
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/core/page/TableDataInfo.java
@@ -0,0 +1,85 @@
+package com.jcdm.common.core.page;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 琛ㄦ牸鍒嗛〉鏁版嵁瀵硅薄
+ * 
+ * @author jc
+ */
+public class TableDataInfo implements Serializable
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 鎬昏褰曟暟 */
+    private long total;
+
+    /** 鍒楄〃鏁版嵁 */
+    private List<?> rows;
+
+    /** 娑堟伅鐘舵�佺爜 */
+    private int code;
+
+    /** 娑堟伅鍐呭 */
+    private String msg;
+
+    /**
+     * 琛ㄦ牸鏁版嵁瀵硅薄
+     */
+    public TableDataInfo()
+    {
+    }
+
+    /**
+     * 鍒嗛〉
+     * 
+     * @param list 鍒楄〃鏁版嵁
+     * @param total 鎬昏褰曟暟
+     */
+    public TableDataInfo(List<?> list, int total)
+    {
+        this.rows = list;
+        this.total = total;
+    }
+
+    public long getTotal()
+    {
+        return total;
+    }
+
+    public void setTotal(long total)
+    {
+        this.total = total;
+    }
+
+    public List<?> getRows()
+    {
+        return rows;
+    }
+
+    public void setRows(List<?> rows)
+    {
+        this.rows = rows;
+    }
+
+    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;
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/core/page/TableSupport.java b/jcdm-common/src/main/java/com/jcdm/common/core/page/TableSupport.java
new file mode 100644
index 0000000..fca1f38
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/core/page/TableSupport.java
@@ -0,0 +1,56 @@
+package com.jcdm.common.core.page;
+
+import com.jcdm.common.core.text.Convert;
+import com.jcdm.common.utils.ServletUtils;
+
+/**
+ * 琛ㄦ牸鏁版嵁澶勭悊
+ * 
+ * @author jc
+ */
+public class TableSupport
+{
+    /**
+     * 褰撳墠璁板綍璧峰绱㈠紩
+     */
+    public static final String PAGE_NUM = "pageNum";
+
+    /**
+     * 姣忛〉鏄剧ず璁板綍鏁�
+     */
+    public static final String PAGE_SIZE = "pageSize";
+
+    /**
+     * 鎺掑簭鍒�
+     */
+    public static final String ORDER_BY_COLUMN = "orderByColumn";
+
+    /**
+     * 鎺掑簭鐨勬柟鍚� "desc" 鎴栬�� "asc".
+     */
+    public static final String IS_ASC = "isAsc";
+
+    /**
+     * 鍒嗛〉鍙傛暟鍚堢悊鍖�
+     */
+    public static final String REASONABLE = "reasonable";
+
+    /**
+     * 灏佽鍒嗛〉瀵硅薄
+     */
+    public static PageDomain getPageDomain()
+    {
+        PageDomain pageDomain = new PageDomain();
+        pageDomain.setPageNum(Convert.toInt(ServletUtils.getParameter(PAGE_NUM), 1));
+        pageDomain.setPageSize(Convert.toInt(ServletUtils.getParameter(PAGE_SIZE), 10));
+        pageDomain.setOrderByColumn(ServletUtils.getParameter(ORDER_BY_COLUMN));
+        pageDomain.setIsAsc(ServletUtils.getParameter(IS_ASC));
+        pageDomain.setReasonable(ServletUtils.getParameterToBool(REASONABLE));
+        return pageDomain;
+    }
+
+    public static PageDomain buildPageRequest()
+    {
+        return getPageDomain();
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/core/redis/MyCache.java b/jcdm-common/src/main/java/com/jcdm/common/core/redis/MyCache.java
new file mode 100644
index 0000000..022c51c
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/core/redis/MyCache.java
@@ -0,0 +1,86 @@
+package com.jcdm.common.core.redis;
+
+import org.springframework.cache.Cache;
+import org.springframework.cache.support.SimpleValueWrapper;
+import org.springframework.stereotype.Component;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Component
+public class MyCache implements Cache {
+
+    // 浣跨敤ConcurrentHashMap浣滀负鏁版嵁鐨勫瓨鍌�
+    private Map<String, Object> storage = new ConcurrentHashMap<>();
+
+    // getName鑾峰彇cache鐨勫悕绉帮紝瀛樺彇鏁版嵁鐨勬椂鍊欑敤鏉ュ尯鍒嗘槸閽堝鍝釜cache鎿嶄綔
+    @Override
+    public String getName() {
+        return null;
+    }
+
+    @Override
+    public Object getNativeCache() {
+        return null;
+    }
+
+    public boolean hasKey(String key){
+        return storage.containsKey(key);
+    }
+
+    @Override
+    public ValueWrapper get(Object key) {
+        String k = key.toString();
+        Object value = storage.get(k);
+
+        // 娉ㄦ剰杩斿洖鐨勬暟鎹紝瑕佸拰瀛樻斁鏃舵帴鏀跺埌鏁版嵁淇濇寔涓�鑷达紝瑕佸皢鏁版嵁鍙嶅簭鍒楀寲鍥炴潵銆�
+        return Objects.isNull(value) ? null : new SimpleValueWrapper(value);
+    }
+
+    @Override
+    public <T> T get(Object key, Class<T> type) {
+        return null;
+    }
+
+    @Override
+    public <T> T get(Object key, Callable<T> valueLoader) {
+        return null;
+    }
+
+    // put鏂规硶锛屽氨鏄墽琛屽皢鏁版嵁杩涜缂撳瓨
+    @Override
+    public void put(Object key, Object value) {
+        if (Objects.isNull(value)) {
+            return;
+        }
+        //瀛樺��
+        storage.put(key.toString(), value);
+    }
+
+    // evict鏂规硶锛屾槸鐢ㄦ潵娓呴櫎鏌愪釜缂撳瓨椤�
+    @Override
+    public void evict(Object key) {
+        storage.remove(key.toString());
+    }
+
+    // 鍒犻櫎闆嗗悎
+    public boolean deleteObject(final Collection collection){
+        collection.forEach(o -> {
+            storage.remove(o.toString());
+        } );
+        return true;
+    }
+
+    // 鑾峰彇鎵�鏈夌殑keys
+    public Collection<String> keys(final String pattern){
+        return storage.keySet();
+    }
+
+    @Override
+    public void clear() {
+
+    }
+}
\ No newline at end of file
diff --git a/jcdm-common/src/main/java/com/jcdm/common/core/redis/RedisCache.java b/jcdm-common/src/main/java/com/jcdm/common/core/redis/RedisCache.java
new file mode 100644
index 0000000..d9f6867
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/core/redis/RedisCache.java
@@ -0,0 +1,279 @@
+package com.jcdm.common.core.redis;
+
+import org.springframework.cache.Cache;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.Collection;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * spring redis 宸ュ叿绫�
+ *
+ * @author jc
+ **/
+@SuppressWarnings(value = { "unchecked", "rawtypes" })
+@Component
+public class RedisCache
+{
+//    @Autowired
+//    public RedisTemplate redisTemplate;
+
+    @Resource
+    public MyCache myCache;
+
+    /**
+     * 缂撳瓨鍩烘湰鐨勫璞★紝Integer銆丼tring銆佸疄浣撶被绛�
+     *
+     * @param key 缂撳瓨鐨勯敭鍊�
+     * @param value 缂撳瓨鐨勫��
+     */
+    public <T> void setCacheObject(final String key, final T value)
+    {
+        myCache.put(key,value);
+//        redisTemplate.opsForValue().set(key, value);
+    }
+
+    /**
+     * 缂撳瓨鍩烘湰鐨勫璞★紝Integer銆丼tring銆佸疄浣撶被绛�
+     *
+     * @param key 缂撳瓨鐨勯敭鍊�
+     * @param value 缂撳瓨鐨勫��
+     * @param timeout 鏃堕棿
+     * @param timeUnit 鏃堕棿棰楃矑搴�
+     */
+    public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit)
+    {
+        myCache.put(key,value);
+//        redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
+    }
+
+    /**
+     * 璁剧疆鏈夋晥鏃堕棿
+     *
+     * @param key Redis閿�
+     * @param timeout 瓒呮椂鏃堕棿
+     * @return true=璁剧疆鎴愬姛锛沠alse=璁剧疆澶辫触
+     */
+    public boolean expire(final String key, final long timeout)
+    {
+        return expire(key, timeout, TimeUnit.SECONDS);
+    }
+
+    /**
+     * 璁剧疆鏈夋晥鏃堕棿
+     *
+     * @param key Redis閿�
+     * @param timeout 瓒呮椂鏃堕棿
+     * @param unit 鏃堕棿鍗曚綅
+     * @return true=璁剧疆鎴愬姛锛沠alse=璁剧疆澶辫触
+     */
+    public boolean expire(final String key, final long timeout, final TimeUnit unit)
+    {
+        return true;
+//        return redisTemplate.expire(key, timeout, unit);
+    }
+
+    /**
+     * 鑾峰彇鏈夋晥鏃堕棿
+     *
+     * @param key Redis閿�
+     * @return 鏈夋晥鏃堕棿
+     */
+//    public long getExpire(final String key)
+//    {
+//        return redisTemplate.getExpire(key);
+//    }
+
+    /**
+     * 鍒ゆ柇 key鏄惁瀛樺湪
+     *
+     * @param key 閿�
+     * @return true 瀛樺湪 false涓嶅瓨鍦�
+     */
+    public Boolean hasKey(String key)
+    {
+        return myCache.hasKey(key);
+//        return redisTemplate.hasKey(key);
+    }
+
+    /**
+     * 鑾峰緱缂撳瓨鐨勫熀鏈璞°��
+     *
+     * @param key 缂撳瓨閿��
+     * @return 缂撳瓨閿�煎搴旂殑鏁版嵁
+     */
+    public <T> T getCacheObject(final String key)
+    {
+        Cache.ValueWrapper valueWrapper = myCache.get(key);
+        if (valueWrapper == null){
+            return null;
+        }else {
+            return (T) valueWrapper.get();
+        }
+//        ValueOperations<String, T> operation = redisTemplate.opsForValue();
+//        return operation.get(key);
+    }
+
+    /**
+     * 鍒犻櫎鍗曚釜瀵硅薄
+     *
+     * @param key
+     */
+    public boolean deleteObject(final String key)
+    {
+        myCache.evict(key);
+        return true;
+//        return redisTemplate.delete(key);
+    }
+
+    /**
+     * 鍒犻櫎闆嗗悎瀵硅薄
+     *
+     * @param collection 澶氫釜瀵硅薄
+     * @return
+     */
+    public boolean deleteObject(final Collection collection)
+    {
+        return myCache.deleteObject(collection);
+//        return redisTemplate.delete(collection) > 0;
+    }
+
+    /**
+     * 缂撳瓨List鏁版嵁
+     *
+     * @param key 缂撳瓨鐨勯敭鍊�
+     * @param dataList 寰呯紦瀛樼殑List鏁版嵁
+     * @return 缂撳瓨鐨勫璞�
+     */
+//    public <T> long setCacheList(final String key, final List<T> dataList)
+//    {
+//        Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
+//        return count == null ? 0 : count;
+//    }
+
+    /**
+     * 鑾峰緱缂撳瓨鐨刲ist瀵硅薄
+     *
+     * @param key 缂撳瓨鐨勯敭鍊�
+     * @return 缂撳瓨閿�煎搴旂殑鏁版嵁
+     */
+//    public <T> List<T> getCacheList(final String key)
+//    {
+//        return redisTemplate.opsForList().range(key, 0, -1);
+//    }
+
+    /**
+     * 缂撳瓨Set
+     *
+     * @param key 缂撳瓨閿��
+     * @param dataSet 缂撳瓨鐨勬暟鎹�
+     * @return 缂撳瓨鏁版嵁鐨勫璞�
+     */
+//    public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet)
+//    {
+//        BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
+//        Iterator<T> it = dataSet.iterator();
+//        while (it.hasNext())
+//        {
+//            setOperation.add(it.next());
+//        }
+//        return setOperation;
+//    }
+
+    /**
+     * 鑾峰緱缂撳瓨鐨剆et
+     *
+     * @param key
+     * @return
+     */
+//    public <T> Set<T> getCacheSet(final String key)
+//    {
+//        return redisTemplate.opsForSet().members(key);
+//    }
+
+    /**
+     * 缂撳瓨Map
+     *
+     * @param key
+     * @param dataMap
+     */
+//    public <T> void setCacheMap(final String key, final Map<String, T> dataMap)
+//    {
+//        if (dataMap != null) {
+//            redisTemplate.opsForHash().putAll(key, dataMap);
+//        }
+//    }
+
+    /**
+     * 鑾峰緱缂撳瓨鐨凪ap
+     *
+     * @param key
+     * @return
+     */
+//    public <T> Map<String, T> getCacheMap(final String key)
+//    {
+//        return redisTemplate.opsForHash().entries(key);
+//    }
+
+    /**
+     * 寰�Hash涓瓨鍏ユ暟鎹�
+     *
+     * @param key Redis閿�
+     * @param hKey Hash閿�
+     * @param value 鍊�
+     */
+//    public <T> void setCacheMapValue(final String key, final String hKey, final T value)
+//    {
+//        redisTemplate.opsForHash().put(key, hKey, value);
+//    }
+
+    /**
+     * 鑾峰彇Hash涓殑鏁版嵁
+     *
+     * @param key Redis閿�
+     * @param hKey Hash閿�
+     * @return Hash涓殑瀵硅薄
+     */
+//    public <T> T getCacheMapValue(final String key, final String hKey)
+//    {
+//        HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
+//        return opsForHash.get(key, hKey);
+//    }
+
+    /**
+     * 鑾峰彇澶氫釜Hash涓殑鏁版嵁
+     *
+     * @param key Redis閿�
+     * @param hKeys Hash閿泦鍚�
+     * @return Hash瀵硅薄闆嗗悎
+     */
+//    public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys)
+//    {
+//        return redisTemplate.opsForHash().multiGet(key, hKeys);
+//    }
+
+    /**
+     * 鍒犻櫎Hash涓殑鏌愭潯鏁版嵁
+     *
+     * @param key Redis閿�
+     * @param hKey Hash閿�
+     * @return 鏄惁鎴愬姛
+     */
+//    public boolean deleteCacheMapValue(final String key, final String hKey)
+//    {
+//        return redisTemplate.opsForHash().delete(key, hKey) > 0;
+//    }
+
+    /**
+     * 鑾峰緱缂撳瓨鐨勫熀鏈璞″垪琛�
+     *
+     * @param pattern 瀛楃涓插墠缂�
+     * @return 瀵硅薄鍒楄〃
+     */
+    public Collection<String> keys(final String pattern)
+    {
+        return myCache.keys(pattern);
+//        return redisTemplate.keys(pattern);
+    }
+}
\ No newline at end of file
diff --git a/jcdm-common/src/main/java/com/jcdm/common/core/text/CharsetKit.java b/jcdm-common/src/main/java/com/jcdm/common/core/text/CharsetKit.java
new file mode 100644
index 0000000..e53fba6
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/core/text/CharsetKit.java
@@ -0,0 +1,86 @@
+package com.jcdm.common.core.text;
+
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import com.jcdm.common.utils.StringUtils;
+
+/**
+ * 瀛楃闆嗗伐鍏风被
+ * 
+ * @author jc
+ */
+public class CharsetKit
+{
+    /** ISO-8859-1 */
+    public static final String ISO_8859_1 = "ISO-8859-1";
+    /** UTF-8 */
+    public static final String UTF_8 = "UTF-8";
+    /** GBK */
+    public static final String GBK = "GBK";
+
+    /** ISO-8859-1 */
+    public static final Charset CHARSET_ISO_8859_1 = Charset.forName(ISO_8859_1);
+    /** UTF-8 */
+    public static final Charset CHARSET_UTF_8 = Charset.forName(UTF_8);
+    /** GBK */
+    public static final Charset CHARSET_GBK = Charset.forName(GBK);
+
+    /**
+     * 杞崲涓篊harset瀵硅薄
+     * 
+     * @param charset 瀛楃闆嗭紝涓虹┖鍒欒繑鍥為粯璁ゅ瓧绗﹂泦
+     * @return Charset
+     */
+    public static Charset charset(String charset)
+    {
+        return StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset);
+    }
+
+    /**
+     * 杞崲瀛楃涓茬殑瀛楃闆嗙紪鐮�
+     * 
+     * @param source 瀛楃涓�
+     * @param srcCharset 婧愬瓧绗﹂泦锛岄粯璁SO-8859-1
+     * @param destCharset 鐩爣瀛楃闆嗭紝榛樿UTF-8
+     * @return 杞崲鍚庣殑瀛楃闆�
+     */
+    public static String convert(String source, String srcCharset, String destCharset)
+    {
+        return convert(source, Charset.forName(srcCharset), Charset.forName(destCharset));
+    }
+
+    /**
+     * 杞崲瀛楃涓茬殑瀛楃闆嗙紪鐮�
+     * 
+     * @param source 瀛楃涓�
+     * @param srcCharset 婧愬瓧绗﹂泦锛岄粯璁SO-8859-1
+     * @param destCharset 鐩爣瀛楃闆嗭紝榛樿UTF-8
+     * @return 杞崲鍚庣殑瀛楃闆�
+     */
+    public static String convert(String source, Charset srcCharset, Charset destCharset)
+    {
+        if (null == srcCharset)
+        {
+            srcCharset = StandardCharsets.ISO_8859_1;
+        }
+
+        if (null == destCharset)
+        {
+            destCharset = StandardCharsets.UTF_8;
+        }
+
+        if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset))
+        {
+            return source;
+        }
+        return new String(source.getBytes(srcCharset), destCharset);
+    }
+
+    /**
+     * @return 绯荤粺瀛楃闆嗙紪鐮�
+     */
+    public static String systemCharset()
+    {
+        return Charset.defaultCharset().name();
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/core/text/Convert.java b/jcdm-common/src/main/java/com/jcdm/common/core/text/Convert.java
new file mode 100644
index 0000000..d9e2e9e
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/core/text/Convert.java
@@ -0,0 +1,1006 @@
+package com.jcdm.common.core.text;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.math.RoundingMode;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.text.NumberFormat;
+import java.util.Set;
+import com.jcdm.common.utils.StringUtils;
+import org.apache.commons.lang3.ArrayUtils;
+
+/**
+ * 绫诲瀷杞崲鍣�
+ *
+ * @author jc
+ */
+public class Convert
+{
+    /**
+     * 杞崲涓哄瓧绗︿覆<br>
+     * 濡傛灉缁欏畾鐨勫�间负null锛屾垨鑰呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     *
+     * @param value 琚浆鎹㈢殑鍊�
+     * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+     * @return 缁撴灉
+     */
+    public static String toStr(Object value, String defaultValue)
+    {
+        if (null == value)
+        {
+            return defaultValue;
+        }
+        if (value instanceof String)
+        {
+            return (String) value;
+        }
+        return value.toString();
+    }
+
+    /**
+     * 杞崲涓哄瓧绗︿覆<br>
+     * 濡傛灉缁欏畾鐨勫�间负<code>null</code>锛屾垨鑰呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     *
+     * @param value 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static String toStr(Object value)
+    {
+        return toStr(value, null);
+    }
+
+    /**
+     * 杞崲涓哄瓧绗�<br>
+     * 濡傛灉缁欏畾鐨勫�间负null锛屾垨鑰呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     *
+     * @param value 琚浆鎹㈢殑鍊�
+     * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+     * @return 缁撴灉
+     */
+    public static Character toChar(Object value, Character defaultValue)
+    {
+        if (null == value)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Character)
+        {
+            return (Character) value;
+        }
+
+        final String valueStr = toStr(value, null);
+        return StringUtils.isEmpty(valueStr) ? defaultValue : valueStr.charAt(0);
+    }
+
+    /**
+     * 杞崲涓哄瓧绗�<br>
+     * 濡傛灉缁欏畾鐨勫�间负<code>null</code>锛屾垨鑰呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     *
+     * @param value 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static Character toChar(Object value)
+    {
+        return toChar(value, null);
+    }
+
+    /**
+     * 杞崲涓篵yte<br>
+     * 濡傛灉缁欏畾鐨勫�间负<code>null</code>锛屾垨鑰呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     *
+     * @param value 琚浆鎹㈢殑鍊�
+     * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+     * @return 缁撴灉
+     */
+    public static Byte toByte(Object value, Byte defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Byte)
+        {
+            return (Byte) value;
+        }
+        if (value instanceof Number)
+        {
+            return ((Number) value).byteValue();
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            return Byte.parseByte(valueStr);
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 杞崲涓篵yte<br>
+     * 濡傛灉缁欏畾鐨勫�间负<code>null</code>锛屾垨鑰呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     *
+     * @param value 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static Byte toByte(Object value)
+    {
+        return toByte(value, null);
+    }
+
+    /**
+     * 杞崲涓篠hort<br>
+     * 濡傛灉缁欏畾鐨勫�间负<code>null</code>锛屾垨鑰呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     *
+     * @param value 琚浆鎹㈢殑鍊�
+     * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+     * @return 缁撴灉
+     */
+    public static Short toShort(Object value, Short defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Short)
+        {
+            return (Short) value;
+        }
+        if (value instanceof Number)
+        {
+            return ((Number) value).shortValue();
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            return Short.parseShort(valueStr.trim());
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 杞崲涓篠hort<br>
+     * 濡傛灉缁欏畾鐨勫�间负<code>null</code>锛屾垨鑰呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     *
+     * @param value 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static Short toShort(Object value)
+    {
+        return toShort(value, null);
+    }
+
+    /**
+     * 杞崲涓篘umber<br>
+     * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     *
+     * @param value 琚浆鎹㈢殑鍊�
+     * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+     * @return 缁撴灉
+     */
+    public static Number toNumber(Object value, Number defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Number)
+        {
+            return (Number) value;
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            return NumberFormat.getInstance().parse(valueStr);
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 杞崲涓篘umber<br>
+     * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     *
+     * @param value 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static Number toNumber(Object value)
+    {
+        return toNumber(value, null);
+    }
+
+    /**
+     * 杞崲涓篿nt<br>
+     * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     *
+     * @param value 琚浆鎹㈢殑鍊�
+     * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+     * @return 缁撴灉
+     */
+    public static Integer toInt(Object value, Integer defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Integer)
+        {
+            return (Integer) value;
+        }
+        if (value instanceof Number)
+        {
+            return ((Number) value).intValue();
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            return Integer.parseInt(valueStr.trim());
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 杞崲涓篿nt<br>
+     * 濡傛灉缁欏畾鐨勫�间负<code>null</code>锛屾垨鑰呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     *
+     * @param value 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static Integer toInt(Object value)
+    {
+        return toInt(value, null);
+    }
+
+    /**
+     * 杞崲涓篒nteger鏁扮粍<br>
+     *
+     * @param str 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static Integer[] toIntArray(String str)
+    {
+        return toIntArray(",", str);
+    }
+
+    /**
+     * 杞崲涓篖ong鏁扮粍<br>
+     *
+     * @param str 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static Long[] toLongArray(String str)
+    {
+        return toLongArray(",", str);
+    }
+
+    /**
+     * 杞崲涓篒nteger鏁扮粍<br>
+     *
+     * @param split 鍒嗛殧绗�
+     * @param split 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static Integer[] toIntArray(String split, String str)
+    {
+        if (StringUtils.isEmpty(str))
+        {
+            return new Integer[] {};
+        }
+        String[] arr = str.split(split);
+        final Integer[] ints = new Integer[arr.length];
+        for (int i = 0; i < arr.length; i++)
+        {
+            final Integer v = toInt(arr[i], 0);
+            ints[i] = v;
+        }
+        return ints;
+    }
+
+    /**
+     * 杞崲涓篖ong鏁扮粍<br>
+     *
+     * @param split 鍒嗛殧绗�
+     * @param str 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static Long[] toLongArray(String split, String str)
+    {
+        if (StringUtils.isEmpty(str))
+        {
+            return new Long[] {};
+        }
+        String[] arr = str.split(split);
+        final Long[] longs = new Long[arr.length];
+        for (int i = 0; i < arr.length; i++)
+        {
+            final Long v = toLong(arr[i], null);
+            longs[i] = v;
+        }
+        return longs;
+    }
+
+    /**
+     * 杞崲涓篠tring鏁扮粍<br>
+     *
+     * @param str 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static String[] toStrArray(String str)
+    {
+        return toStrArray(",", str);
+    }
+
+    /**
+     * 杞崲涓篠tring鏁扮粍<br>
+     *
+     * @param split 鍒嗛殧绗�
+     * @param split 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static String[] toStrArray(String split, String str)
+    {
+        return str.split(split);
+    }
+
+    /**
+     * 杞崲涓簂ong<br>
+     * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     *
+     * @param value 琚浆鎹㈢殑鍊�
+     * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+     * @return 缁撴灉
+     */
+    public static Long toLong(Object value, Long defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Long)
+        {
+            return (Long) value;
+        }
+        if (value instanceof Number)
+        {
+            return ((Number) value).longValue();
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            // 鏀寔绉戝璁℃暟娉�
+            return new BigDecimal(valueStr.trim()).longValue();
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 杞崲涓簂ong<br>
+     * 濡傛灉缁欏畾鐨勫�间负<code>null</code>锛屾垨鑰呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     *
+     * @param value 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static Long toLong(Object value)
+    {
+        return toLong(value, null);
+    }
+
+    /**
+     * 杞崲涓篸ouble<br>
+     * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     *
+     * @param value 琚浆鎹㈢殑鍊�
+     * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+     * @return 缁撴灉
+     */
+    public static Double toDouble(Object value, Double defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Double)
+        {
+            return (Double) value;
+        }
+        if (value instanceof Number)
+        {
+            return ((Number) value).doubleValue();
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            // 鏀寔绉戝璁℃暟娉�
+            return new BigDecimal(valueStr.trim()).doubleValue();
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 杞崲涓篸ouble<br>
+     * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     *
+     * @param value 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static Double toDouble(Object value)
+    {
+        return toDouble(value, null);
+    }
+
+    /**
+     * 杞崲涓篎loat<br>
+     * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     *
+     * @param value 琚浆鎹㈢殑鍊�
+     * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+     * @return 缁撴灉
+     */
+    public static Float toFloat(Object value, Float defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Float)
+        {
+            return (Float) value;
+        }
+        if (value instanceof Number)
+        {
+            return ((Number) value).floatValue();
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            return Float.parseFloat(valueStr.trim());
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 杞崲涓篎loat<br>
+     * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     *
+     * @param value 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static Float toFloat(Object value)
+    {
+        return toFloat(value, null);
+    }
+
+    /**
+     * 杞崲涓篵oolean<br>
+     * String鏀寔鐨勫�间负锛歵rue銆乫alse銆亂es銆乷k銆乶o锛�1,0 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     *
+     * @param value 琚浆鎹㈢殑鍊�
+     * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+     * @return 缁撴灉
+     */
+    public static Boolean toBool(Object value, Boolean defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Boolean)
+        {
+            return (Boolean) value;
+        }
+        String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        valueStr = valueStr.trim().toLowerCase();
+        switch (valueStr)
+        {
+            case "true":
+            case "yes":
+            case "ok":
+            case "1":
+                return true;
+            case "false":
+            case "no":
+            case "0":
+                return false;
+            default:
+                return defaultValue;
+        }
+    }
+
+    /**
+     * 杞崲涓篵oolean<br>
+     * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     *
+     * @param value 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static Boolean toBool(Object value)
+    {
+        return toBool(value, null);
+    }
+
+    /**
+     * 杞崲涓篍num瀵硅薄<br>
+     * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+     *
+     * @param clazz Enum鐨凜lass
+     * @param value 鍊�
+     * @param defaultValue 榛樿鍊�
+     * @return Enum
+     */
+    public static <E extends Enum<E>> E toEnum(Class<E> clazz, Object value, E defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (clazz.isAssignableFrom(value.getClass()))
+        {
+            @SuppressWarnings("unchecked")
+            E myE = (E) value;
+            return myE;
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            return Enum.valueOf(clazz, valueStr);
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 杞崲涓篍num瀵硅薄<br>
+     * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+     *
+     * @param clazz Enum鐨凜lass
+     * @param value 鍊�
+     * @return Enum
+     */
+    public static <E extends Enum<E>> E toEnum(Class<E> clazz, Object value)
+    {
+        return toEnum(clazz, value, null);
+    }
+
+    /**
+     * 杞崲涓築igInteger<br>
+     * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     *
+     * @param value 琚浆鎹㈢殑鍊�
+     * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+     * @return 缁撴灉
+     */
+    public static BigInteger toBigInteger(Object value, BigInteger defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof BigInteger)
+        {
+            return (BigInteger) value;
+        }
+        if (value instanceof Long)
+        {
+            return BigInteger.valueOf((Long) value);
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            return new BigInteger(valueStr);
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 杞崲涓築igInteger<br>
+     * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     *
+     * @param value 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static BigInteger toBigInteger(Object value)
+    {
+        return toBigInteger(value, null);
+    }
+
+    /**
+     * 杞崲涓築igDecimal<br>
+     * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     *
+     * @param value 琚浆鎹㈢殑鍊�
+     * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+     * @return 缁撴灉
+     */
+    public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof BigDecimal)
+        {
+            return (BigDecimal) value;
+        }
+        if (value instanceof Long)
+        {
+            return new BigDecimal((Long) value);
+        }
+        if (value instanceof Double)
+        {
+            return BigDecimal.valueOf((Double) value);
+        }
+        if (value instanceof Integer)
+        {
+            return new BigDecimal((Integer) value);
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            return new BigDecimal(valueStr);
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 杞崲涓築igDecimal<br>
+     * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     *
+     * @param value 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static BigDecimal toBigDecimal(Object value)
+    {
+        return toBigDecimal(value, null);
+    }
+
+    /**
+     * 灏嗗璞¤浆涓哄瓧绗︿覆<br>
+     * 1銆丅yte鏁扮粍鍜孊yteBuffer浼氳杞崲涓哄搴斿瓧绗︿覆鐨勬暟缁� 2銆佸璞℃暟缁勪細璋冪敤Arrays.toString鏂规硶
+     *
+     * @param obj 瀵硅薄
+     * @return 瀛楃涓�
+     */
+    public static String utf8Str(Object obj)
+    {
+        return str(obj, CharsetKit.CHARSET_UTF_8);
+    }
+
+    /**
+     * 灏嗗璞¤浆涓哄瓧绗︿覆<br>
+     * 1銆丅yte鏁扮粍鍜孊yteBuffer浼氳杞崲涓哄搴斿瓧绗︿覆鐨勬暟缁� 2銆佸璞℃暟缁勪細璋冪敤Arrays.toString鏂规硶
+     *
+     * @param obj 瀵硅薄
+     * @param charsetName 瀛楃闆�
+     * @return 瀛楃涓�
+     */
+    public static String str(Object obj, String charsetName)
+    {
+        return str(obj, Charset.forName(charsetName));
+    }
+
+    /**
+     * 灏嗗璞¤浆涓哄瓧绗︿覆<br>
+     * 1銆丅yte鏁扮粍鍜孊yteBuffer浼氳杞崲涓哄搴斿瓧绗︿覆鐨勬暟缁� 2銆佸璞℃暟缁勪細璋冪敤Arrays.toString鏂规硶
+     *
+     * @param obj 瀵硅薄
+     * @param charset 瀛楃闆�
+     * @return 瀛楃涓�
+     */
+    public static String str(Object obj, Charset charset)
+    {
+        if (null == obj)
+        {
+            return null;
+        }
+
+        if (obj instanceof String)
+        {
+            return (String) obj;
+        }
+        else if (obj instanceof byte[])
+        {
+            return str((byte[]) obj, charset);
+        }
+        else if (obj instanceof Byte[])
+        {
+            byte[] bytes = ArrayUtils.toPrimitive((Byte[]) obj);
+            return str(bytes, charset);
+        }
+        else if (obj instanceof ByteBuffer)
+        {
+            return str((ByteBuffer) obj, charset);
+        }
+        return obj.toString();
+    }
+
+    /**
+     * 灏哹yte鏁扮粍杞负瀛楃涓�
+     *
+     * @param bytes byte鏁扮粍
+     * @param charset 瀛楃闆�
+     * @return 瀛楃涓�
+     */
+    public static String str(byte[] bytes, String charset)
+    {
+        return str(bytes, StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset));
+    }
+
+    /**
+     * 瑙g爜瀛楄妭鐮�
+     *
+     * @param data 瀛楃涓�
+     * @param charset 瀛楃闆嗭紝濡傛灉姝ゅ瓧娈典负绌猴紝鍒欒В鐮佺殑缁撴灉鍙栧喅浜庡钩鍙�
+     * @return 瑙g爜鍚庣殑瀛楃涓�
+     */
+    public static String str(byte[] data, Charset charset)
+    {
+        if (data == null)
+        {
+            return null;
+        }
+
+        if (null == charset)
+        {
+            return new String(data);
+        }
+        return new String(data, charset);
+    }
+
+    /**
+     * 灏嗙紪鐮佺殑byteBuffer鏁版嵁杞崲涓哄瓧绗︿覆
+     *
+     * @param data 鏁版嵁
+     * @param charset 瀛楃闆嗭紝濡傛灉涓虹┖浣跨敤褰撳墠绯荤粺瀛楃闆�
+     * @return 瀛楃涓�
+     */
+    public static String str(ByteBuffer data, String charset)
+    {
+        if (data == null)
+        {
+            return null;
+        }
+
+        return str(data, Charset.forName(charset));
+    }
+
+    /**
+     * 灏嗙紪鐮佺殑byteBuffer鏁版嵁杞崲涓哄瓧绗︿覆
+     *
+     * @param data 鏁版嵁
+     * @param charset 瀛楃闆嗭紝濡傛灉涓虹┖浣跨敤褰撳墠绯荤粺瀛楃闆�
+     * @return 瀛楃涓�
+     */
+    public static String str(ByteBuffer data, Charset charset)
+    {
+        if (null == charset)
+        {
+            charset = Charset.defaultCharset();
+        }
+        return charset.decode(data).toString();
+    }
+
+    // ----------------------------------------------------------------------- 鍏ㄨ鍗婅杞崲
+    /**
+     * 鍗婅杞叏瑙�
+     *
+     * @param input String.
+     * @return 鍏ㄨ瀛楃涓�.
+     */
+    public static String toSBC(String input)
+    {
+        return toSBC(input, null);
+    }
+
+    /**
+     * 鍗婅杞叏瑙�
+     *
+     * @param input String
+     * @param notConvertSet 涓嶆浛鎹㈢殑瀛楃闆嗗悎
+     * @return 鍏ㄨ瀛楃涓�.
+     */
+    public static String toSBC(String input, Set<Character> notConvertSet)
+    {
+        char[] c = input.toCharArray();
+        for (int i = 0; i < c.length; i++)
+        {
+            if (null != notConvertSet && notConvertSet.contains(c[i]))
+            {
+                // 璺宠繃涓嶆浛鎹㈢殑瀛楃
+                continue;
+            }
+
+            if (c[i] == ' ')
+            {
+                c[i] = '\u3000';
+            }
+            else if (c[i] < '\177')
+            {
+                c[i] = (char) (c[i] + 65248);
+
+            }
+        }
+        return new String(c);
+    }
+
+    /**
+     * 鍏ㄨ杞崐瑙�
+     *
+     * @param input String.
+     * @return 鍗婅瀛楃涓�
+     */
+    public static String toDBC(String input)
+    {
+        return toDBC(input, null);
+    }
+
+    /**
+     * 鏇挎崲鍏ㄨ涓哄崐瑙�
+     *
+     * @param text 鏂囨湰
+     * @param notConvertSet 涓嶆浛鎹㈢殑瀛楃闆嗗悎
+     * @return 鏇挎崲鍚庣殑瀛楃
+     */
+    public static String toDBC(String text, Set<Character> notConvertSet)
+    {
+        char[] c = text.toCharArray();
+        for (int i = 0; i < c.length; i++)
+        {
+            if (null != notConvertSet && notConvertSet.contains(c[i]))
+            {
+                // 璺宠繃涓嶆浛鎹㈢殑瀛楃
+                continue;
+            }
+
+            if (c[i] == '\u3000')
+            {
+                c[i] = ' ';
+            }
+            else if (c[i] > '\uFF00' && c[i] < '\uFF5F')
+            {
+                c[i] = (char) (c[i] - 65248);
+            }
+        }
+        String returnString = new String(c);
+
+        return returnString;
+    }
+
+    /**
+     * 鏁板瓧閲戦澶у啓杞崲 鍏堝啓涓畬鏁寸殑鐒跺悗灏嗗闆舵嬀鏇挎崲鎴愰浂
+     *
+     * @param n 鏁板瓧
+     * @return 涓枃澶у啓鏁板瓧
+     */
+    public static String digitUppercase(double n)
+    {
+        String[] fraction = { "瑙�", "鍒�" };
+        String[] digit = { "闆�", "澹�", "璐�", "鍙�", "鑲�", "浼�", "闄�", "鏌�", "鎹�", "鐜�" };
+        String[][] unit = { { "鍏�", "涓�", "浜�" }, { "", "鎷�", "浣�", "浠�" } };
+
+        String head = n < 0 ? "璐�" : "";
+        n = Math.abs(n);
+
+        String s = "";
+        for (int i = 0; i < fraction.length; i++)
+        {
+            // 浼樺寲double璁$畻绮惧害涓㈠け闂
+            BigDecimal nNum = new BigDecimal(n);
+            BigDecimal decimal = new BigDecimal(10);
+            BigDecimal scale = nNum.multiply(decimal).setScale(2, RoundingMode.HALF_EVEN);
+            double d = scale.doubleValue();
+            s += (digit[(int) (Math.floor(d * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(闆�.)+", "");
+        }
+        if (s.length() < 1)
+        {
+            s = "鏁�";
+        }
+        int integerPart = (int) Math.floor(n);
+
+        for (int i = 0; i < unit[0].length && integerPart > 0; i++)
+        {
+            String p = "";
+            for (int j = 0; j < unit[1].length && n > 0; j++)
+            {
+                p = digit[integerPart % 10] + unit[1][j] + p;
+                integerPart = integerPart / 10;
+            }
+            s = p.replaceAll("(闆�.)*闆�$", "").replaceAll("^$", "闆�") + unit[0][i] + s;
+        }
+        return head + s.replaceAll("(闆�.)*闆跺厓", "鍏�").replaceFirst("(闆�.)+", "").replaceAll("(闆�.)+", "闆�").replaceAll("^鏁�$", "闆跺厓鏁�");
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/core/text/StrFormatter.java b/jcdm-common/src/main/java/com/jcdm/common/core/text/StrFormatter.java
new file mode 100644
index 0000000..b850f4e
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/core/text/StrFormatter.java
@@ -0,0 +1,92 @@
+package com.jcdm.common.core.text;
+
+import com.jcdm.common.utils.StringUtils;
+
+/**
+ * 瀛楃涓叉牸寮忓寲
+ * 
+ * @author jc
+ */
+public class StrFormatter
+{
+    public static final String EMPTY_JSON = "{}";
+    public static final char C_BACKSLASH = '\\';
+    public static final char C_DELIM_START = '{';
+    public static final char C_DELIM_END = '}';
+
+    /**
+     * 鏍煎紡鍖栧瓧绗︿覆<br>
+     * 姝ゆ柟娉曞彧鏄畝鍗曞皢鍗犱綅绗� {} 鎸夌収椤哄簭鏇挎崲涓哄弬鏁�<br>
+     * 濡傛灉鎯宠緭鍑� {} 浣跨敤 \\杞箟 { 鍗冲彲锛屽鏋滄兂杈撳嚭 {} 涔嬪墠鐨� \ 浣跨敤鍙岃浆涔夌 \\\\ 鍗冲彲<br>
+     * 渚嬶細<br>
+     * 閫氬父浣跨敤锛歠ormat("this is {} for {}", "a", "b") -> this is a for b<br>
+     * 杞箟{}锛� format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
+     * 杞箟\锛� format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
+     * 
+     * @param strPattern 瀛楃涓叉ā鏉�
+     * @param argArray 鍙傛暟鍒楄〃
+     * @return 缁撴灉
+     */
+    public static String format(final String strPattern, final Object... argArray)
+    {
+        if (StringUtils.isEmpty(strPattern) || StringUtils.isEmpty(argArray))
+        {
+            return strPattern;
+        }
+        final int strPatternLength = strPattern.length();
+
+        // 鍒濆鍖栧畾涔夊ソ鐨勯暱搴︿互鑾峰緱鏇村ソ鐨勬�ц兘
+        StringBuilder sbuf = new StringBuilder(strPatternLength + 50);
+
+        int handledPosition = 0;
+        int delimIndex;// 鍗犱綅绗︽墍鍦ㄤ綅缃�
+        for (int argIndex = 0; argIndex < argArray.length; argIndex++)
+        {
+            delimIndex = strPattern.indexOf(EMPTY_JSON, handledPosition);
+            if (delimIndex == -1)
+            {
+                if (handledPosition == 0)
+                {
+                    return strPattern;
+                }
+                else
+                { // 瀛楃涓叉ā鏉垮墿浣欓儴鍒嗕笉鍐嶅寘鍚崰浣嶇锛屽姞鍏ュ墿浣欓儴鍒嗗悗杩斿洖缁撴灉
+                    sbuf.append(strPattern, handledPosition, strPatternLength);
+                    return sbuf.toString();
+                }
+            }
+            else
+            {
+                if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH)
+                {
+                    if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH)
+                    {
+                        // 杞箟绗︿箣鍓嶈繕鏈変竴涓浆涔夌锛屽崰浣嶇渚濇棫鏈夋晥
+                        sbuf.append(strPattern, handledPosition, delimIndex - 1);
+                        sbuf.append(Convert.utf8Str(argArray[argIndex]));
+                        handledPosition = delimIndex + 2;
+                    }
+                    else
+                    {
+                        // 鍗犱綅绗﹁杞箟
+                        argIndex--;
+                        sbuf.append(strPattern, handledPosition, delimIndex - 1);
+                        sbuf.append(C_DELIM_START);
+                        handledPosition = delimIndex + 1;
+                    }
+                }
+                else
+                {
+                    // 姝e父鍗犱綅绗�
+                    sbuf.append(strPattern, handledPosition, delimIndex);
+                    sbuf.append(Convert.utf8Str(argArray[argIndex]));
+                    handledPosition = delimIndex + 2;
+                }
+            }
+        }
+        // 鍔犲叆鏈�鍚庝竴涓崰浣嶇鍚庢墍鏈夌殑瀛楃
+        sbuf.append(strPattern, handledPosition, strPattern.length());
+
+        return sbuf.toString();
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/enums/BusinessStatus.java b/jcdm-common/src/main/java/com/jcdm/common/enums/BusinessStatus.java
new file mode 100644
index 0000000..9d16417
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/enums/BusinessStatus.java
@@ -0,0 +1,20 @@
+package com.jcdm.common.enums;
+
+/**
+ * 鎿嶄綔鐘舵��
+ * 
+ * @author jc
+ *
+ */
+public enum BusinessStatus
+{
+    /**
+     * 鎴愬姛
+     */
+    SUCCESS,
+
+    /**
+     * 澶辫触
+     */
+    FAIL,
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/enums/BusinessType.java b/jcdm-common/src/main/java/com/jcdm/common/enums/BusinessType.java
new file mode 100644
index 0000000..941f6e2
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/enums/BusinessType.java
@@ -0,0 +1,59 @@
+package com.jcdm.common.enums;
+
+/**
+ * 涓氬姟鎿嶄綔绫诲瀷
+ * 
+ * @author jc
+ */
+public enum BusinessType
+{
+    /**
+     * 鍏跺畠
+     */
+    OTHER,
+
+    /**
+     * 鏂板
+     */
+    INSERT,
+
+    /**
+     * 淇敼
+     */
+    UPDATE,
+
+    /**
+     * 鍒犻櫎
+     */
+    DELETE,
+
+    /**
+     * 鎺堟潈
+     */
+    GRANT,
+
+    /**
+     * 瀵煎嚭
+     */
+    EXPORT,
+
+    /**
+     * 瀵煎叆
+     */
+    IMPORT,
+
+    /**
+     * 寮洪��
+     */
+    FORCE,
+
+    /**
+     * 鐢熸垚浠g爜
+     */
+    GENCODE,
+    
+    /**
+     * 娓呯┖鏁版嵁
+     */
+    CLEAN,
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/enums/DataSourceType.java b/jcdm-common/src/main/java/com/jcdm/common/enums/DataSourceType.java
new file mode 100644
index 0000000..53f5cba
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/enums/DataSourceType.java
@@ -0,0 +1,19 @@
+package com.jcdm.common.enums;
+
+/**
+ * 鏁版嵁婧�
+ * 
+ * @author jc
+ */
+public enum DataSourceType
+{
+    /**
+     * 涓诲簱
+     */
+    MASTER,
+
+    /**
+     * 浠庡簱
+     */
+    SLAVE
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/enums/HttpMethod.java b/jcdm-common/src/main/java/com/jcdm/common/enums/HttpMethod.java
new file mode 100644
index 0000000..e1a0e92
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/enums/HttpMethod.java
@@ -0,0 +1,36 @@
+package com.jcdm.common.enums;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.springframework.lang.Nullable;
+
+/**
+ * 璇锋眰鏂瑰紡
+ *
+ * @author jc
+ */
+public enum HttpMethod
+{
+    GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE;
+
+    private static final Map<String, HttpMethod> mappings = new HashMap<>(16);
+
+    static
+    {
+        for (HttpMethod httpMethod : values())
+        {
+            mappings.put(httpMethod.name(), httpMethod);
+        }
+    }
+
+    @Nullable
+    public static HttpMethod resolve(@Nullable String method)
+    {
+        return (method != null ? mappings.get(method) : null);
+    }
+
+    public boolean matches(String method)
+    {
+        return (this == resolve(method));
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/enums/LimitType.java b/jcdm-common/src/main/java/com/jcdm/common/enums/LimitType.java
new file mode 100644
index 0000000..9849d01
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/enums/LimitType.java
@@ -0,0 +1,20 @@
+package com.jcdm.common.enums;
+
+/**
+ * 闄愭祦绫诲瀷
+ *
+ * @author jc
+ */
+
+public enum LimitType
+{
+    /**
+     * 榛樿绛栫暐鍏ㄥ眬闄愭祦
+     */
+    DEFAULT,
+
+    /**
+     * 鏍规嵁璇锋眰鑰匢P杩涜闄愭祦
+     */
+    IP
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/enums/OperatorType.java b/jcdm-common/src/main/java/com/jcdm/common/enums/OperatorType.java
new file mode 100644
index 0000000..646996d
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/enums/OperatorType.java
@@ -0,0 +1,24 @@
+package com.jcdm.common.enums;
+
+/**
+ * 鎿嶄綔浜虹被鍒�
+ * 
+ * @author jc
+ */
+public enum OperatorType
+{
+    /**
+     * 鍏跺畠
+     */
+    OTHER,
+
+    /**
+     * 鍚庡彴鐢ㄦ埛
+     */
+    MANAGE,
+
+    /**
+     * 鎵嬫満绔敤鎴�
+     */
+    MOBILE
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/enums/UserStatus.java b/jcdm-common/src/main/java/com/jcdm/common/enums/UserStatus.java
new file mode 100644
index 0000000..f31f9b7
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/enums/UserStatus.java
@@ -0,0 +1,30 @@
+package com.jcdm.common.enums;
+
+/**
+ * 鐢ㄦ埛鐘舵��
+ * 
+ * @author jc
+ */
+public enum UserStatus
+{
+    OK("0", "姝e父"), DISABLE("1", "鍋滅敤"), DELETED("2", "鍒犻櫎");
+
+    private final String code;
+    private final String info;
+
+    UserStatus(String code, String info)
+    {
+        this.code = code;
+        this.info = info;
+    }
+
+    public String getCode()
+    {
+        return code;
+    }
+
+    public String getInfo()
+    {
+        return info;
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/exception/DemoModeException.java b/jcdm-common/src/main/java/com/jcdm/common/exception/DemoModeException.java
new file mode 100644
index 0000000..3847f23
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/exception/DemoModeException.java
@@ -0,0 +1,15 @@
+package com.jcdm.common.exception;
+
+/**
+ * 婕旂ず妯″紡寮傚父
+ * 
+ * @author jc
+ */
+public class DemoModeException extends RuntimeException
+{
+    private static final long serialVersionUID = 1L;
+
+    public DemoModeException()
+    {
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/exception/GlobalException.java b/jcdm-common/src/main/java/com/jcdm/common/exception/GlobalException.java
new file mode 100644
index 0000000..341edcf
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/exception/GlobalException.java
@@ -0,0 +1,58 @@
+package com.jcdm.common.exception;
+
+/**
+ * 鍏ㄥ眬寮傚父
+ * 
+ * @author jc
+ */
+public class GlobalException extends RuntimeException
+{
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 閿欒鎻愮ず
+     */
+    private String message;
+
+    /**
+     * 閿欒鏄庣粏锛屽唴閮ㄨ皟璇曢敊璇�
+     *
+     * 鍜� {@link CommonResult#getDetailMessage()} 涓�鑷寸殑璁捐
+     */
+    private String detailMessage;
+
+    /**
+     * 绌烘瀯閫犳柟娉曪紝閬垮厤鍙嶅簭鍒楀寲闂
+     */
+    public GlobalException()
+    {
+    }
+
+    public GlobalException(String message)
+    {
+        this.message = message;
+    }
+
+    public String getDetailMessage()
+    {
+        return detailMessage;
+    }
+
+    public GlobalException setDetailMessage(String detailMessage)
+    {
+        this.detailMessage = detailMessage;
+        return this;
+    }
+
+    @Override
+    public String getMessage()
+    {
+        return message;
+    }
+
+    public GlobalException setMessage(String message)
+    {
+        this.message = message;
+        return this;
+    }
+}
\ No newline at end of file
diff --git a/jcdm-common/src/main/java/com/jcdm/common/exception/ServiceException.java b/jcdm-common/src/main/java/com/jcdm/common/exception/ServiceException.java
new file mode 100644
index 0000000..7ffe439
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/exception/ServiceException.java
@@ -0,0 +1,74 @@
+package com.jcdm.common.exception;
+
+/**
+ * 涓氬姟寮傚父
+ * 
+ * @author jc
+ */
+public final class ServiceException extends RuntimeException
+{
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 閿欒鐮�
+     */
+    private Integer code;
+
+    /**
+     * 閿欒鎻愮ず
+     */
+    private String message;
+
+    /**
+     * 閿欒鏄庣粏锛屽唴閮ㄨ皟璇曢敊璇�
+     *
+     * 鍜� {@link CommonResult#getDetailMessage()} 涓�鑷寸殑璁捐
+     */
+    private String detailMessage;
+
+    /**
+     * 绌烘瀯閫犳柟娉曪紝閬垮厤鍙嶅簭鍒楀寲闂
+     */
+    public ServiceException()
+    {
+    }
+
+    public ServiceException(String message)
+    {
+        this.message = message;
+    }
+
+    public ServiceException(String message, Integer code)
+    {
+        this.message = message;
+        this.code = code;
+    }
+
+    public String getDetailMessage()
+    {
+        return detailMessage;
+    }
+
+    @Override
+    public String getMessage()
+    {
+        return message;
+    }
+
+    public Integer getCode()
+    {
+        return code;
+    }
+
+    public ServiceException setMessage(String message)
+    {
+        this.message = message;
+        return this;
+    }
+
+    public ServiceException setDetailMessage(String detailMessage)
+    {
+        this.detailMessage = detailMessage;
+        return this;
+    }
+}
\ No newline at end of file
diff --git a/jcdm-common/src/main/java/com/jcdm/common/exception/UtilException.java b/jcdm-common/src/main/java/com/jcdm/common/exception/UtilException.java
new file mode 100644
index 0000000..bc05e18
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/exception/UtilException.java
@@ -0,0 +1,26 @@
+package com.jcdm.common.exception;
+
+/**
+ * 宸ュ叿绫诲紓甯�
+ * 
+ * @author jc
+ */
+public class UtilException extends RuntimeException
+{
+    private static final long serialVersionUID = 8247610319171014183L;
+
+    public UtilException(Throwable e)
+    {
+        super(e.getMessage(), e);
+    }
+
+    public UtilException(String message)
+    {
+        super(message);
+    }
+
+    public UtilException(String message, Throwable throwable)
+    {
+        super(message, throwable);
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/exception/base/BaseException.java b/jcdm-common/src/main/java/com/jcdm/common/exception/base/BaseException.java
new file mode 100644
index 0000000..af172bb
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/exception/base/BaseException.java
@@ -0,0 +1,97 @@
+package com.jcdm.common.exception.base;
+
+import com.jcdm.common.utils.MessageUtils;
+import com.jcdm.common.utils.StringUtils;
+
+/**
+ * 鍩虹寮傚父
+ * 
+ * @author jc
+ */
+public class BaseException extends RuntimeException
+{
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 鎵�灞炴ā鍧�
+     */
+    private String module;
+
+    /**
+     * 閿欒鐮�
+     */
+    private String code;
+
+    /**
+     * 閿欒鐮佸搴旂殑鍙傛暟
+     */
+    private Object[] args;
+
+    /**
+     * 閿欒娑堟伅
+     */
+    private String defaultMessage;
+
+    public BaseException(String module, String code, Object[] args, String defaultMessage)
+    {
+        this.module = module;
+        this.code = code;
+        this.args = args;
+        this.defaultMessage = defaultMessage;
+    }
+
+    public BaseException(String module, String code, Object[] args)
+    {
+        this(module, code, args, null);
+    }
+
+    public BaseException(String module, String defaultMessage)
+    {
+        this(module, null, null, defaultMessage);
+    }
+
+    public BaseException(String code, Object[] args)
+    {
+        this(null, code, args, null);
+    }
+
+    public BaseException(String defaultMessage)
+    {
+        this(null, null, null, defaultMessage);
+    }
+
+    @Override
+    public String getMessage()
+    {
+        String message = null;
+        if (!StringUtils.isEmpty(code))
+        {
+            message = MessageUtils.message(code, args);
+        }
+        if (message == null)
+        {
+            message = defaultMessage;
+        }
+        return message;
+    }
+
+    public String getModule()
+    {
+        return module;
+    }
+
+    public String getCode()
+    {
+        return code;
+    }
+
+    public Object[] getArgs()
+    {
+        return args;
+    }
+
+    public String getDefaultMessage()
+    {
+        return defaultMessage;
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/exception/file/FileException.java b/jcdm-common/src/main/java/com/jcdm/common/exception/file/FileException.java
new file mode 100644
index 0000000..c485307
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/exception/file/FileException.java
@@ -0,0 +1,19 @@
+package com.jcdm.common.exception.file;
+
+import com.jcdm.common.exception.base.BaseException;
+
+/**
+ * 鏂囦欢淇℃伅寮傚父绫�
+ * 
+ * @author jc
+ */
+public class FileException extends BaseException
+{
+    private static final long serialVersionUID = 1L;
+
+    public FileException(String code, Object[] args)
+    {
+        super("file", code, args, null);
+    }
+
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/exception/file/FileNameLengthLimitExceededException.java b/jcdm-common/src/main/java/com/jcdm/common/exception/file/FileNameLengthLimitExceededException.java
new file mode 100644
index 0000000..36c1594
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/exception/file/FileNameLengthLimitExceededException.java
@@ -0,0 +1,16 @@
+package com.jcdm.common.exception.file;
+
+/**
+ * 鏂囦欢鍚嶇О瓒呴暱闄愬埗寮傚父绫�
+ * 
+ * @author jc
+ */
+public class FileNameLengthLimitExceededException extends FileException
+{
+    private static final long serialVersionUID = 1L;
+
+    public FileNameLengthLimitExceededException(int defaultFileNameLength)
+    {
+        super("upload.filename.exceed.length", new Object[] { defaultFileNameLength });
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/exception/file/FileSizeLimitExceededException.java b/jcdm-common/src/main/java/com/jcdm/common/exception/file/FileSizeLimitExceededException.java
new file mode 100644
index 0000000..cc01cce
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/exception/file/FileSizeLimitExceededException.java
@@ -0,0 +1,16 @@
+package com.jcdm.common.exception.file;
+
+/**
+ * 鏂囦欢鍚嶅ぇ灏忛檺鍒跺紓甯哥被
+ * 
+ * @author jc
+ */
+public class FileSizeLimitExceededException extends FileException
+{
+    private static final long serialVersionUID = 1L;
+
+    public FileSizeLimitExceededException(long defaultMaxSize)
+    {
+        super("upload.exceed.maxSize", new Object[] { defaultMaxSize });
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/exception/file/FileUploadException.java b/jcdm-common/src/main/java/com/jcdm/common/exception/file/FileUploadException.java
new file mode 100644
index 0000000..3631243
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/exception/file/FileUploadException.java
@@ -0,0 +1,61 @@
+package com.jcdm.common.exception.file;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ * 鏂囦欢涓婁紶寮傚父绫�
+ * 
+ * @author jc
+ */
+public class FileUploadException extends Exception
+{
+
+    private static final long serialVersionUID = 1L;
+
+    private final Throwable cause;
+
+    public FileUploadException()
+    {
+        this(null, null);
+    }
+
+    public FileUploadException(final String msg)
+    {
+        this(msg, null);
+    }
+
+    public FileUploadException(String msg, Throwable cause)
+    {
+        super(msg);
+        this.cause = cause;
+    }
+
+    @Override
+    public void printStackTrace(PrintStream stream)
+    {
+        super.printStackTrace(stream);
+        if (cause != null)
+        {
+            stream.println("Caused by:");
+            cause.printStackTrace(stream);
+        }
+    }
+
+    @Override
+    public void printStackTrace(PrintWriter writer)
+    {
+        super.printStackTrace(writer);
+        if (cause != null)
+        {
+            writer.println("Caused by:");
+            cause.printStackTrace(writer);
+        }
+    }
+
+    @Override
+    public Throwable getCause()
+    {
+        return cause;
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/exception/file/InvalidExtensionException.java b/jcdm-common/src/main/java/com/jcdm/common/exception/file/InvalidExtensionException.java
new file mode 100644
index 0000000..a503ad1
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/exception/file/InvalidExtensionException.java
@@ -0,0 +1,80 @@
+package com.jcdm.common.exception.file;
+
+import java.util.Arrays;
+
+/**
+ * 鏂囦欢涓婁紶 璇紓甯哥被
+ * 
+ * @author jc
+ */
+public class InvalidExtensionException extends FileUploadException
+{
+    private static final long serialVersionUID = 1L;
+
+    private String[] allowedExtension;
+    private String extension;
+    private String filename;
+
+    public InvalidExtensionException(String[] allowedExtension, String extension, String filename)
+    {
+        super("鏂囦欢[" + filename + "]鍚庣紑[" + extension + "]涓嶆纭紝璇蜂笂浼�" + Arrays.toString(allowedExtension) + "鏍煎紡");
+        this.allowedExtension = allowedExtension;
+        this.extension = extension;
+        this.filename = filename;
+    }
+
+    public String[] getAllowedExtension()
+    {
+        return allowedExtension;
+    }
+
+    public String getExtension()
+    {
+        return extension;
+    }
+
+    public String getFilename()
+    {
+        return filename;
+    }
+
+    public static class InvalidImageExtensionException extends InvalidExtensionException
+    {
+        private static final long serialVersionUID = 1L;
+
+        public InvalidImageExtensionException(String[] allowedExtension, String extension, String filename)
+        {
+            super(allowedExtension, extension, filename);
+        }
+    }
+
+    public static class InvalidFlashExtensionException extends InvalidExtensionException
+    {
+        private static final long serialVersionUID = 1L;
+
+        public InvalidFlashExtensionException(String[] allowedExtension, String extension, String filename)
+        {
+            super(allowedExtension, extension, filename);
+        }
+    }
+
+    public static class InvalidMediaExtensionException extends InvalidExtensionException
+    {
+        private static final long serialVersionUID = 1L;
+
+        public InvalidMediaExtensionException(String[] allowedExtension, String extension, String filename)
+        {
+            super(allowedExtension, extension, filename);
+        }
+    }
+
+    public static class InvalidVideoExtensionException extends InvalidExtensionException
+    {
+        private static final long serialVersionUID = 1L;
+
+        public InvalidVideoExtensionException(String[] allowedExtension, String extension, String filename)
+        {
+            super(allowedExtension, extension, filename);
+        }
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/exception/job/TaskException.java b/jcdm-common/src/main/java/com/jcdm/common/exception/job/TaskException.java
new file mode 100644
index 0000000..2a7d22a
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/exception/job/TaskException.java
@@ -0,0 +1,34 @@
+package com.jcdm.common.exception.job;
+
+/**
+ * 璁″垝绛栫暐寮傚父
+ * 
+ * @author jc
+ */
+public class TaskException extends Exception
+{
+    private static final long serialVersionUID = 1L;
+
+    private Code code;
+
+    public TaskException(String msg, Code code)
+    {
+        this(msg, code, null);
+    }
+
+    public TaskException(String msg, Code code, Exception nestedEx)
+    {
+        super(msg, nestedEx);
+        this.code = code;
+    }
+
+    public Code getCode()
+    {
+        return code;
+    }
+
+    public enum Code
+    {
+        TASK_EXISTS, NO_TASK_EXISTS, TASK_ALREADY_STARTED, UNKNOWN, CONFIG_ERROR, TASK_NODE_NOT_AVAILABLE
+    }
+}
\ No newline at end of file
diff --git a/jcdm-common/src/main/java/com/jcdm/common/exception/user/BlackListException.java b/jcdm-common/src/main/java/com/jcdm/common/exception/user/BlackListException.java
new file mode 100644
index 0000000..41a6da8
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/exception/user/BlackListException.java
@@ -0,0 +1,16 @@
+package com.jcdm.common.exception.user;
+
+/**
+ * 榛戝悕鍗旾P寮傚父绫�
+ * 
+ * @author jc
+ */
+public class BlackListException extends UserException
+{
+    private static final long serialVersionUID = 1L;
+
+    public BlackListException()
+    {
+        super("login.blocked", null);
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/exception/user/CaptchaException.java b/jcdm-common/src/main/java/com/jcdm/common/exception/user/CaptchaException.java
new file mode 100644
index 0000000..0605281
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/exception/user/CaptchaException.java
@@ -0,0 +1,16 @@
+package com.jcdm.common.exception.user;
+
+/**
+ * 楠岃瘉鐮侀敊璇紓甯哥被
+ * 
+ * @author jc
+ */
+public class CaptchaException extends UserException
+{
+    private static final long serialVersionUID = 1L;
+
+    public CaptchaException()
+    {
+        super("user.jcaptcha.error", null);
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/exception/user/CaptchaExpireException.java b/jcdm-common/src/main/java/com/jcdm/common/exception/user/CaptchaExpireException.java
new file mode 100644
index 0000000..369c4a0
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/exception/user/CaptchaExpireException.java
@@ -0,0 +1,16 @@
+package com.jcdm.common.exception.user;
+
+/**
+ * 楠岃瘉鐮佸け鏁堝紓甯哥被
+ * 
+ * @author jc
+ */
+public class CaptchaExpireException extends UserException
+{
+    private static final long serialVersionUID = 1L;
+
+    public CaptchaExpireException()
+    {
+        super("user.jcaptcha.expire", null);
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/exception/user/UserException.java b/jcdm-common/src/main/java/com/jcdm/common/exception/user/UserException.java
new file mode 100644
index 0000000..b32e956
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/exception/user/UserException.java
@@ -0,0 +1,18 @@
+package com.jcdm.common.exception.user;
+
+import com.jcdm.common.exception.base.BaseException;
+
+/**
+ * 鐢ㄦ埛淇℃伅寮傚父绫�
+ * 
+ * @author jc
+ */
+public class UserException extends BaseException
+{
+    private static final long serialVersionUID = 1L;
+
+    public UserException(String code, Object[] args)
+    {
+        super("user", code, args, null);
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/exception/user/UserNotExistsException.java b/jcdm-common/src/main/java/com/jcdm/common/exception/user/UserNotExistsException.java
new file mode 100644
index 0000000..7a63f5e
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/exception/user/UserNotExistsException.java
@@ -0,0 +1,16 @@
+package com.jcdm.common.exception.user;
+
+/**
+ * 鐢ㄦ埛涓嶅瓨鍦ㄥ紓甯哥被
+ * 
+ * @author jc
+ */
+public class UserNotExistsException extends UserException
+{
+    private static final long serialVersionUID = 1L;
+
+    public UserNotExistsException()
+    {
+        super("user.not.exists", null);
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/exception/user/UserPasswordNotMatchException.java b/jcdm-common/src/main/java/com/jcdm/common/exception/user/UserPasswordNotMatchException.java
new file mode 100644
index 0000000..e306e20
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/exception/user/UserPasswordNotMatchException.java
@@ -0,0 +1,16 @@
+package com.jcdm.common.exception.user;
+
+/**
+ * 鐢ㄦ埛瀵嗙爜涓嶆纭垨涓嶇鍚堣鑼冨紓甯哥被
+ * 
+ * @author jc
+ */
+public class UserPasswordNotMatchException extends UserException
+{
+    private static final long serialVersionUID = 1L;
+
+    public UserPasswordNotMatchException()
+    {
+        super("user.password.not.match", null);
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/exception/user/UserPasswordRetryLimitExceedException.java b/jcdm-common/src/main/java/com/jcdm/common/exception/user/UserPasswordRetryLimitExceedException.java
new file mode 100644
index 0000000..f004cc1
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/exception/user/UserPasswordRetryLimitExceedException.java
@@ -0,0 +1,16 @@
+package com.jcdm.common.exception.user;
+
+/**
+ * 鐢ㄦ埛閿欒鏈�澶ф鏁板紓甯哥被
+ * 
+ * @author jc
+ */
+public class UserPasswordRetryLimitExceedException extends UserException
+{
+    private static final long serialVersionUID = 1L;
+
+    public UserPasswordRetryLimitExceedException(int retryLimitCount, int lockTime)
+    {
+        super("user.password.retry.limit.exceed", new Object[] { retryLimitCount, lockTime });
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/filter/PropertyPreExcludeFilter.java b/jcdm-common/src/main/java/com/jcdm/common/filter/PropertyPreExcludeFilter.java
new file mode 100644
index 0000000..61a1bde
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/filter/PropertyPreExcludeFilter.java
@@ -0,0 +1,24 @@
+package com.jcdm.common.filter;
+
+import com.alibaba.fastjson2.filter.SimplePropertyPreFilter;
+
+/**
+ * 鎺掗櫎JSON鏁忔劅灞炴��
+ * 
+ * @author jc
+ */
+public class PropertyPreExcludeFilter extends SimplePropertyPreFilter
+{
+    public PropertyPreExcludeFilter()
+    {
+    }
+
+    public PropertyPreExcludeFilter addExcludes(String... filters)
+    {
+        for (int i = 0; i < filters.length; i++)
+        {
+            this.getExcludes().add(filters[i]);
+        }
+        return this;
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/filter/RepeatableFilter.java b/jcdm-common/src/main/java/com/jcdm/common/filter/RepeatableFilter.java
new file mode 100644
index 0000000..ee2e2b0
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/filter/RepeatableFilter.java
@@ -0,0 +1,52 @@
+package com.jcdm.common.filter;
+
+import java.io.IOException;
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import org.springframework.http.MediaType;
+import com.jcdm.common.utils.StringUtils;
+
+/**
+ * Repeatable 杩囨护鍣�
+ * 
+ * @author jc
+ */
+public class RepeatableFilter implements Filter
+{
+    @Override
+    public void init(FilterConfig filterConfig) throws ServletException
+    {
+
+    }
+
+    @Override
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+            throws IOException, ServletException
+    {
+        ServletRequest requestWrapper = null;
+        if (request instanceof HttpServletRequest
+                && StringUtils.startsWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE))
+        {
+            requestWrapper = new RepeatedlyRequestWrapper((HttpServletRequest) request, response);
+        }
+        if (null == requestWrapper)
+        {
+            chain.doFilter(request, response);
+        }
+        else
+        {
+            chain.doFilter(requestWrapper, response);
+        }
+    }
+
+    @Override
+    public void destroy()
+    {
+
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/filter/RepeatedlyRequestWrapper.java b/jcdm-common/src/main/java/com/jcdm/common/filter/RepeatedlyRequestWrapper.java
new file mode 100644
index 0000000..02cb453
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/filter/RepeatedlyRequestWrapper.java
@@ -0,0 +1,76 @@
+package com.jcdm.common.filter;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import javax.servlet.ReadListener;
+import javax.servlet.ServletInputStream;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import com.jcdm.common.utils.http.HttpHelper;
+import com.jcdm.common.constant.Constants;
+
+/**
+ * 鏋勫缓鍙噸澶嶈鍙杋nputStream鐨剅equest
+ * 
+ * @author jc
+ */
+public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper
+{
+    private final byte[] body;
+
+    public RepeatedlyRequestWrapper(HttpServletRequest request, ServletResponse response) throws IOException
+    {
+        super(request);
+        request.setCharacterEncoding(Constants.UTF8);
+        response.setCharacterEncoding(Constants.UTF8);
+
+        body = HttpHelper.getBodyString(request).getBytes(Constants.UTF8);
+    }
+
+    @Override
+    public BufferedReader getReader() throws IOException
+    {
+        return new BufferedReader(new InputStreamReader(getInputStream()));
+    }
+
+    @Override
+    public ServletInputStream getInputStream() throws IOException
+    {
+        final ByteArrayInputStream bais = new ByteArrayInputStream(body);
+        return new ServletInputStream()
+        {
+            @Override
+            public int read() throws IOException
+            {
+                return bais.read();
+            }
+
+            @Override
+            public int available() throws IOException
+            {
+                return body.length;
+            }
+
+            @Override
+            public boolean isFinished()
+            {
+                return false;
+            }
+
+            @Override
+            public boolean isReady()
+            {
+                return false;
+            }
+
+            @Override
+            public void setReadListener(ReadListener readListener)
+            {
+
+            }
+        };
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/filter/XssFilter.java b/jcdm-common/src/main/java/com/jcdm/common/filter/XssFilter.java
new file mode 100644
index 0000000..0ef5f97
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/filter/XssFilter.java
@@ -0,0 +1,75 @@
+package com.jcdm.common.filter;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.common.enums.HttpMethod;
+
+/**
+ * 闃叉XSS鏀诲嚮鐨勮繃婊ゅ櫒
+ * 
+ * @author jc
+ */
+public class XssFilter implements Filter
+{
+    /**
+     * 鎺掗櫎閾炬帴
+     */
+    public List<String> excludes = new ArrayList<>();
+
+    @Override
+    public void init(FilterConfig filterConfig) throws ServletException
+    {
+        String tempExcludes = filterConfig.getInitParameter("excludes");
+        if (StringUtils.isNotEmpty(tempExcludes))
+        {
+            String[] url = tempExcludes.split(",");
+            for (int i = 0; url != null && i < url.length; i++)
+            {
+                excludes.add(url[i]);
+            }
+        }
+    }
+
+    @Override
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+            throws IOException, ServletException
+    {
+        HttpServletRequest req = (HttpServletRequest) request;
+        HttpServletResponse resp = (HttpServletResponse) response;
+        if (handleExcludeURL(req, resp))
+        {
+            chain.doFilter(request, response);
+            return;
+        }
+        XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
+        chain.doFilter(xssRequest, response);
+    }
+
+    private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response)
+    {
+        String url = request.getServletPath();
+        String method = request.getMethod();
+        // GET DELETE 涓嶈繃婊�
+        if (method == null || HttpMethod.GET.matches(method) || HttpMethod.DELETE.matches(method))
+        {
+            return true;
+        }
+        return StringUtils.matches(url, excludes);
+    }
+
+    @Override
+    public void destroy()
+    {
+
+    }
+}
\ No newline at end of file
diff --git a/jcdm-common/src/main/java/com/jcdm/common/filter/XssHttpServletRequestWrapper.java b/jcdm-common/src/main/java/com/jcdm/common/filter/XssHttpServletRequestWrapper.java
new file mode 100644
index 0000000..b5de816
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/filter/XssHttpServletRequestWrapper.java
@@ -0,0 +1,111 @@
+package com.jcdm.common.filter;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import javax.servlet.ReadListener;
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import org.apache.commons.io.IOUtils;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.common.utils.html.EscapeUtil;
+
+/**
+ * XSS杩囨护澶勭悊
+ * 
+ * @author jc
+ */
+public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper
+{
+    /**
+     * @param request
+     */
+    public XssHttpServletRequestWrapper(HttpServletRequest request)
+    {
+        super(request);
+    }
+
+    @Override
+    public String[] getParameterValues(String name)
+    {
+        String[] values = super.getParameterValues(name);
+        if (values != null)
+        {
+            int length = values.length;
+            String[] escapesValues = new String[length];
+            for (int i = 0; i < length; i++)
+            {
+                // 闃瞲ss鏀诲嚮鍜岃繃婊ゅ墠鍚庣┖鏍�
+                escapesValues[i] = EscapeUtil.clean(values[i]).trim();
+            }
+            return escapesValues;
+        }
+        return super.getParameterValues(name);
+    }
+
+    @Override
+    public ServletInputStream getInputStream() throws IOException
+    {
+        // 闈瀓son绫诲瀷锛岀洿鎺ヨ繑鍥�
+        if (!isJsonRequest())
+        {
+            return super.getInputStream();
+        }
+
+        // 涓虹┖锛岀洿鎺ヨ繑鍥�
+        String json = IOUtils.toString(super.getInputStream(), "utf-8");
+        if (StringUtils.isEmpty(json))
+        {
+            return super.getInputStream();
+        }
+
+        // xss杩囨护
+        json = EscapeUtil.clean(json).trim();
+        byte[] jsonBytes = json.getBytes("utf-8");
+        final ByteArrayInputStream bis = new ByteArrayInputStream(jsonBytes);
+        return new ServletInputStream()
+        {
+            @Override
+            public boolean isFinished()
+            {
+                return true;
+            }
+
+            @Override
+            public boolean isReady()
+            {
+                return true;
+            }
+
+            @Override
+            public int available() throws IOException
+            {
+                return jsonBytes.length;
+            }
+
+            @Override
+            public void setReadListener(ReadListener readListener)
+            {
+            }
+
+            @Override
+            public int read() throws IOException
+            {
+                return bis.read();
+            }
+        };
+    }
+
+    /**
+     * 鏄惁鏄疛son璇锋眰
+     * 
+     * @param request
+     */
+    public boolean isJsonRequest()
+    {
+        String header = super.getHeader(HttpHeaders.CONTENT_TYPE);
+        return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE);
+    }
+}
\ No newline at end of file
diff --git a/jcdm-common/src/main/java/com/jcdm/common/utils/Arith.java b/jcdm-common/src/main/java/com/jcdm/common/utils/Arith.java
new file mode 100644
index 0000000..3bc586c
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/utils/Arith.java
@@ -0,0 +1,114 @@
+package com.jcdm.common.utils;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+
+/**
+ * 绮剧‘鐨勬诞鐐规暟杩愮畻
+ * 
+ * @author jc
+ */
+public class Arith
+{
+
+    /** 榛樿闄ゆ硶杩愮畻绮惧害 */
+    private static final int DEF_DIV_SCALE = 10;
+
+    /** 杩欎釜绫讳笉鑳藉疄渚嬪寲 */
+    private Arith()
+    {
+    }
+
+    /**
+     * 鎻愪緵绮剧‘鐨勫姞娉曡繍绠椼��
+     * @param v1 琚姞鏁�
+     * @param v2 鍔犳暟
+     * @return 涓や釜鍙傛暟鐨勫拰
+     */
+    public static double add(double v1, double v2)
+    {
+        BigDecimal b1 = new BigDecimal(Double.toString(v1));
+        BigDecimal b2 = new BigDecimal(Double.toString(v2));
+        return b1.add(b2).doubleValue();
+    }
+
+    /**
+     * 鎻愪緵绮剧‘鐨勫噺娉曡繍绠椼��
+     * @param v1 琚噺鏁�
+     * @param v2 鍑忔暟
+     * @return 涓や釜鍙傛暟鐨勫樊
+     */
+    public static double sub(double v1, double v2)
+    {
+        BigDecimal b1 = new BigDecimal(Double.toString(v1));
+        BigDecimal b2 = new BigDecimal(Double.toString(v2));
+        return b1.subtract(b2).doubleValue();
+    }
+
+    /**
+     * 鎻愪緵绮剧‘鐨勪箻娉曡繍绠椼��
+     * @param v1 琚箻鏁�
+     * @param v2 涔樻暟
+     * @return 涓や釜鍙傛暟鐨勭Н
+     */
+    public static double mul(double v1, double v2)
+    {
+        BigDecimal b1 = new BigDecimal(Double.toString(v1));
+        BigDecimal b2 = new BigDecimal(Double.toString(v2));
+        return b1.multiply(b2).doubleValue();
+    }
+
+    /**
+     * 鎻愪緵锛堢浉瀵癸級绮剧‘鐨勯櫎娉曡繍绠楋紝褰撳彂鐢熼櫎涓嶅敖鐨勬儏鍐垫椂锛岀簿纭埌
+     * 灏忔暟鐐逛互鍚�10浣嶏紝浠ュ悗鐨勬暟瀛楀洓鑸嶄簲鍏ャ��
+     * @param v1 琚櫎鏁�
+     * @param v2 闄ゆ暟
+     * @return 涓や釜鍙傛暟鐨勫晢
+     */
+    public static double div(double v1, double v2)
+    {
+        return div(v1, v2, DEF_DIV_SCALE);
+    }
+
+    /**
+     * 鎻愪緵锛堢浉瀵癸級绮剧‘鐨勯櫎娉曡繍绠椼�傚綋鍙戠敓闄や笉灏界殑鎯呭喌鏃讹紝鐢眘cale鍙傛暟鎸�
+     * 瀹氱簿搴︼紝浠ュ悗鐨勬暟瀛楀洓鑸嶄簲鍏ャ��
+     * @param v1 琚櫎鏁�
+     * @param v2 闄ゆ暟
+     * @param scale 琛ㄧず琛ㄧず闇�瑕佺簿纭埌灏忔暟鐐逛互鍚庡嚑浣嶃��
+     * @return 涓や釜鍙傛暟鐨勫晢
+     */
+    public static double div(double v1, double v2, int scale)
+    {
+        if (scale < 0)
+        {
+            throw new IllegalArgumentException(
+                    "The scale must be a positive integer or zero");
+        }
+        BigDecimal b1 = new BigDecimal(Double.toString(v1));
+        BigDecimal b2 = new BigDecimal(Double.toString(v2));
+        if (b1.compareTo(BigDecimal.ZERO) == 0)
+        {
+            return BigDecimal.ZERO.doubleValue();
+        }
+        return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue();
+    }
+
+    /**
+     * 鎻愪緵绮剧‘鐨勫皬鏁颁綅鍥涜垗浜斿叆澶勭悊銆�
+     * @param v 闇�瑕佸洓鑸嶄簲鍏ョ殑鏁板瓧
+     * @param scale 灏忔暟鐐瑰悗淇濈暀鍑犱綅
+     * @return 鍥涜垗浜斿叆鍚庣殑缁撴灉
+     */
+    public static double round(double v, int scale)
+    {
+        if (scale < 0)
+        {
+            throw new IllegalArgumentException(
+                    "The scale must be a positive integer or zero");
+        }
+        BigDecimal b = new BigDecimal(Double.toString(v));
+        BigDecimal one = BigDecimal.ONE;
+        return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue();
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/utils/DateUtils.java b/jcdm-common/src/main/java/com/jcdm/common/utils/DateUtils.java
new file mode 100644
index 0000000..279444f
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/utils/DateUtils.java
@@ -0,0 +1,191 @@
+package com.jcdm.common.utils;
+
+import java.lang.management.ManagementFactory;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.util.Date;
+import org.apache.commons.lang3.time.DateFormatUtils;
+
+/**
+ * 鏃堕棿宸ュ叿绫�
+ * 
+ * @author jc
+ */
+public class DateUtils extends org.apache.commons.lang3.time.DateUtils
+{
+    public static String YYYY = "yyyy";
+
+    public static String YYYY_MM = "yyyy-MM";
+
+    public static String YYYY_MM_DD = "yyyy-MM-dd";
+
+    public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
+
+    public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
+
+    private static String[] parsePatterns = {
+            "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", 
+            "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
+            "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
+
+    /**
+     * 鑾峰彇褰撳墠Date鍨嬫棩鏈�
+     * 
+     * @return Date() 褰撳墠鏃ユ湡
+     */
+    public static Date getNowDate()
+    {
+        return new Date();
+    }
+
+    /**
+     * 鑾峰彇褰撳墠鏃ユ湡, 榛樿鏍煎紡涓簓yyy-MM-dd
+     * 
+     * @return String
+     */
+    public static String getDate()
+    {
+        return dateTimeNow(YYYY_MM_DD);
+    }
+
+    public static final String getTime()
+    {
+        return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
+    }
+
+    public static final String dateTimeNow()
+    {
+        return dateTimeNow(YYYYMMDDHHMMSS);
+    }
+
+    public static final String dateTimeNow(final String format)
+    {
+        return parseDateToStr(format, new Date());
+    }
+
+    public static final String dateTime(final Date date)
+    {
+        return parseDateToStr(YYYY_MM_DD, date);
+    }
+
+    public static final String parseDateToStr(final String format, final Date date)
+    {
+        return new SimpleDateFormat(format).format(date);
+    }
+
+    public static final Date dateTime(final String format, final String ts)
+    {
+        try
+        {
+            return new SimpleDateFormat(format).parse(ts);
+        }
+        catch (ParseException e)
+        {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * 鏃ユ湡璺緞 鍗冲勾/鏈�/鏃� 濡�2018/08/08
+     */
+    public static final String datePath()
+    {
+        Date now = new Date();
+        return DateFormatUtils.format(now, "yyyy/MM/dd");
+    }
+
+    /**
+     * 鏃ユ湡璺緞 鍗冲勾/鏈�/鏃� 濡�20180808
+     */
+    public static final String dateTime()
+    {
+        Date now = new Date();
+        return DateFormatUtils.format(now, "yyyyMMdd");
+    }
+
+    /**
+     * 鏃ユ湡鍨嬪瓧绗︿覆杞寲涓烘棩鏈� 鏍煎紡
+     */
+    public static Date parseDate(Object str)
+    {
+        if (str == null)
+        {
+            return null;
+        }
+        try
+        {
+            return parseDate(str.toString(), parsePatterns);
+        }
+        catch (ParseException e)
+        {
+            return null;
+        }
+    }
+
+    /**
+     * 鑾峰彇鏈嶅姟鍣ㄥ惎鍔ㄦ椂闂�
+     */
+    public static Date getServerStartDate()
+    {
+        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
+        return new Date(time);
+    }
+
+    /**
+     * 璁$畻鐩稿樊澶╂暟
+     */
+    public static int differentDaysByMillisecond(Date date1, Date date2)
+    {
+        return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24)));
+    }
+
+    /**
+     * 璁$畻鏃堕棿宸�
+     *
+     * @param endDate 鏈�鍚庢椂闂�
+     * @param startTime 寮�濮嬫椂闂�
+     * @return 鏃堕棿宸紙澶�/灏忔椂/鍒嗛挓锛�
+     */
+    public static String timeDistance(Date endDate, Date startTime)
+    {
+        long nd = 1000 * 24 * 60 * 60;
+        long nh = 1000 * 60 * 60;
+        long nm = 1000 * 60;
+        // long ns = 1000;
+        // 鑾峰緱涓や釜鏃堕棿鐨勬绉掓椂闂村樊寮�
+        long diff = endDate.getTime() - startTime.getTime();
+        // 璁$畻宸灏戝ぉ
+        long day = diff / nd;
+        // 璁$畻宸灏戝皬鏃�
+        long hour = diff % nd / nh;
+        // 璁$畻宸灏戝垎閽�
+        long min = diff % nd % nh / nm;
+        // 璁$畻宸灏戠//杈撳嚭缁撴灉
+        // long sec = diff % nd % nh % nm / ns;
+        return day + "澶�" + hour + "灏忔椂" + min + "鍒嗛挓";
+    }
+
+    /**
+     * 澧炲姞 LocalDateTime ==> Date
+     */
+    public static Date toDate(LocalDateTime temporalAccessor)
+    {
+        ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault());
+        return Date.from(zdt.toInstant());
+    }
+
+    /**
+     * 澧炲姞 LocalDate ==> Date
+     */
+    public static Date toDate(LocalDate temporalAccessor)
+    {
+        LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0));
+        ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
+        return Date.from(zdt.toInstant());
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/utils/DictUtils.java b/jcdm-common/src/main/java/com/jcdm/common/utils/DictUtils.java
new file mode 100644
index 0000000..7917aea
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/utils/DictUtils.java
@@ -0,0 +1,204 @@
+package com.jcdm.common.utils;
+
+import java.util.Collection;
+import java.util.List;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONArray;
+import com.jcdm.common.constant.CacheConstants;
+import com.jcdm.common.core.domain.entity.SysDictData;
+import com.jcdm.common.core.redis.RedisCache;
+import com.jcdm.common.utils.spring.SpringUtils;
+
+/**
+ * 瀛楀吀宸ュ叿绫�
+ * 
+ * @author jc
+ */
+public class DictUtils
+{
+    /**
+     * 鍒嗛殧绗�
+     */
+    public static final String SEPARATOR = ",";
+
+    /**
+     * 璁剧疆瀛楀吀缂撳瓨
+     * 
+     * @param key 鍙傛暟閿�
+     * @param dictDatas 瀛楀吀鏁版嵁鍒楄〃
+     */
+    public static void setDictCache(String key, List<SysDictData> dictDatas)
+    {
+        SpringUtils.getBean(RedisCache.class).setCacheObject(getCacheKey(key), dictDatas);
+    }
+
+//    /**
+//     * 鑾峰彇瀛楀吀缂撳瓨
+//     *
+//     * @param key 鍙傛暟閿�
+//     * @return dictDatas 瀛楀吀鏁版嵁鍒楄〃
+//     */
+//    public static List<SysDictData> getDictCache(String key)
+//    {
+//        JSONArray arrayCache = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key));
+//        if (StringUtils.isNotNull(arrayCache))
+//        {
+//            return arrayCache.toList(SysDictData.class);
+//        }
+//        return null;
+//    }
+    /**
+     * 鑾峰彇瀛楀吀缂撳瓨
+     *
+     * @param key 鍙傛暟閿�
+     * @return dictDatas 瀛楀吀鏁版嵁鍒楄〃
+     */
+    public static List<SysDictData> getDictCache(String key)
+    {
+        JSONArray arrayCache = JSONArray.parseArray(JSON.toJSONString(SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key))));
+//        JSONArray arrayCache = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key));
+        if (StringUtils.isNotNull(arrayCache))
+        {
+            return arrayCache.toList(SysDictData.class);
+        }
+        return null;
+    }
+
+    /**
+     * 鏍规嵁瀛楀吀绫诲瀷鍜屽瓧鍏稿�艰幏鍙栧瓧鍏告爣绛�
+     * 
+     * @param dictType 瀛楀吀绫诲瀷
+     * @param dictValue 瀛楀吀鍊�
+     * @return 瀛楀吀鏍囩
+     */
+    public static String getDictLabel(String dictType, String dictValue)
+    {
+        return getDictLabel(dictType, dictValue, SEPARATOR);
+    }
+
+    /**
+     * 鏍规嵁瀛楀吀绫诲瀷鍜屽瓧鍏告爣绛捐幏鍙栧瓧鍏稿��
+     * 
+     * @param dictType 瀛楀吀绫诲瀷
+     * @param dictLabel 瀛楀吀鏍囩
+     * @return 瀛楀吀鍊�
+     */
+    public static String getDictValue(String dictType, String dictLabel)
+    {
+        return getDictValue(dictType, dictLabel, SEPARATOR);
+    }
+
+    /**
+     * 鏍规嵁瀛楀吀绫诲瀷鍜屽瓧鍏稿�艰幏鍙栧瓧鍏告爣绛�
+     * 
+     * @param dictType 瀛楀吀绫诲瀷
+     * @param dictValue 瀛楀吀鍊�
+     * @param separator 鍒嗛殧绗�
+     * @return 瀛楀吀鏍囩
+     */
+    public static String getDictLabel(String dictType, String dictValue, String separator)
+    {
+        StringBuilder propertyString = new StringBuilder();
+        List<SysDictData> datas = getDictCache(dictType);
+
+        if (StringUtils.isNotNull(datas))
+        {
+            if (StringUtils.containsAny(separator, dictValue))
+            {
+                for (SysDictData dict : datas)
+                {
+                    for (String value : dictValue.split(separator))
+                    {
+                        if (value.equals(dict.getDictValue()))
+                        {
+                            propertyString.append(dict.getDictLabel()).append(separator);
+                            break;
+                        }
+                    }
+                }
+            }
+            else
+            {
+                for (SysDictData dict : datas)
+                {
+                    if (dictValue.equals(dict.getDictValue()))
+                    {
+                        return dict.getDictLabel();
+                    }
+                }
+            }
+        }
+        return StringUtils.stripEnd(propertyString.toString(), separator);
+    }
+
+    /**
+     * 鏍规嵁瀛楀吀绫诲瀷鍜屽瓧鍏告爣绛捐幏鍙栧瓧鍏稿��
+     * 
+     * @param dictType 瀛楀吀绫诲瀷
+     * @param dictLabel 瀛楀吀鏍囩
+     * @param separator 鍒嗛殧绗�
+     * @return 瀛楀吀鍊�
+     */
+    public static String getDictValue(String dictType, String dictLabel, String separator)
+    {
+        StringBuilder propertyString = new StringBuilder();
+        List<SysDictData> datas = getDictCache(dictType);
+
+        if (StringUtils.containsAny(separator, dictLabel) && StringUtils.isNotEmpty(datas))
+        {
+            for (SysDictData dict : datas)
+            {
+                for (String label : dictLabel.split(separator))
+                {
+                    if (label.equals(dict.getDictLabel()))
+                    {
+                        propertyString.append(dict.getDictValue()).append(separator);
+                        break;
+                    }
+                }
+            }
+        }
+        else
+        {
+            for (SysDictData dict : datas)
+            {
+                if (dictLabel.equals(dict.getDictLabel()))
+                {
+                    return dict.getDictValue();
+                }
+            }
+        }
+        return StringUtils.stripEnd(propertyString.toString(), separator);
+    }
+
+    /**
+     * 鍒犻櫎鎸囧畾瀛楀吀缂撳瓨
+     * 
+     * @param key 瀛楀吀閿�
+     */
+    public static void removeDictCache(String key)
+    {
+        SpringUtils.getBean(RedisCache.class).deleteObject(getCacheKey(key));
+    }
+
+    /**
+     * 娓呯┖瀛楀吀缂撳瓨
+     */
+    public static void clearDictCache()
+    {
+        Collection<String> keys = SpringUtils.getBean(RedisCache.class).keys(CacheConstants.SYS_DICT_KEY + "*");
+        SpringUtils.getBean(RedisCache.class).deleteObject(keys);
+    }
+
+    /**
+     * 璁剧疆cache key
+     * 
+     * @param configKey 鍙傛暟閿�
+     * @return 缂撳瓨閿甼ey
+     */
+    public static String getCacheKey(String configKey)
+    {
+        return CacheConstants.SYS_DICT_KEY + configKey;
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/utils/ExceptionUtil.java b/jcdm-common/src/main/java/com/jcdm/common/utils/ExceptionUtil.java
new file mode 100644
index 0000000..a79aafe
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/utils/ExceptionUtil.java
@@ -0,0 +1,39 @@
+package com.jcdm.common.utils;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import org.apache.commons.lang3.exception.ExceptionUtils;
+
+/**
+ * 閿欒淇℃伅澶勭悊绫汇��
+ *
+ * @author jc
+ */
+public class ExceptionUtil
+{
+    /**
+     * 鑾峰彇exception鐨勮缁嗛敊璇俊鎭��
+     */
+    public static String getExceptionMessage(Throwable e)
+    {
+        StringWriter sw = new StringWriter();
+        e.printStackTrace(new PrintWriter(sw, true));
+        return sw.toString();
+    }
+
+    public static String getRootErrorMessage(Exception e)
+    {
+        Throwable root = ExceptionUtils.getRootCause(e);
+        root = (root == null ? e : root);
+        if (root == null)
+        {
+            return "";
+        }
+        String msg = root.getMessage();
+        if (msg == null)
+        {
+            return "null";
+        }
+        return StringUtils.defaultString(msg);
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/utils/LogUtils.java b/jcdm-common/src/main/java/com/jcdm/common/utils/LogUtils.java
new file mode 100644
index 0000000..2e00a90
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/utils/LogUtils.java
@@ -0,0 +1,18 @@
+package com.jcdm.common.utils;
+
+/**
+ * 澶勭悊骞惰褰曟棩蹇楁枃浠�
+ * 
+ * @author jc
+ */
+public class LogUtils
+{
+    public static String getBlock(Object msg)
+    {
+        if (msg == null)
+        {
+            msg = "";
+        }
+        return "[" + msg.toString() + "]";
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/utils/MessageUtils.java b/jcdm-common/src/main/java/com/jcdm/common/utils/MessageUtils.java
new file mode 100644
index 0000000..56efabc
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/utils/MessageUtils.java
@@ -0,0 +1,26 @@
+package com.jcdm.common.utils;
+
+import org.springframework.context.MessageSource;
+import org.springframework.context.i18n.LocaleContextHolder;
+import com.jcdm.common.utils.spring.SpringUtils;
+
+/**
+ * 鑾峰彇i18n璧勬簮鏂囦欢
+ * 
+ * @author jc
+ */
+public class MessageUtils
+{
+    /**
+     * 鏍规嵁娑堟伅閿拰鍙傛暟 鑾峰彇娑堟伅 濮旀墭缁檚pring messageSource
+     *
+     * @param code 娑堟伅閿�
+     * @param args 鍙傛暟
+     * @return 鑾峰彇鍥介檯鍖栫炕璇戝��
+     */
+    public static String message(String code, Object... args)
+    {
+        MessageSource messageSource = SpringUtils.getBean(MessageSource.class);
+        return messageSource.getMessage(code, args, LocaleContextHolder.getLocale());
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/utils/PageUtils.java b/jcdm-common/src/main/java/com/jcdm/common/utils/PageUtils.java
new file mode 100644
index 0000000..7b2cea2
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/utils/PageUtils.java
@@ -0,0 +1,35 @@
+package com.jcdm.common.utils;
+
+import com.github.pagehelper.PageHelper;
+import com.jcdm.common.core.page.PageDomain;
+import com.jcdm.common.core.page.TableSupport;
+import com.jcdm.common.utils.sql.SqlUtil;
+
+/**
+ * 鍒嗛〉宸ュ叿绫�
+ * 
+ * @author jc
+ */
+public class PageUtils extends PageHelper
+{
+    /**
+     * 璁剧疆璇锋眰鍒嗛〉鏁版嵁
+     */
+    public static void startPage()
+    {
+        PageDomain pageDomain = TableSupport.buildPageRequest();
+        Integer pageNum = pageDomain.getPageNum();
+        Integer pageSize = pageDomain.getPageSize();
+        String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
+        Boolean reasonable = pageDomain.getReasonable();
+        PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable);
+    }
+
+    /**
+     * 娓呯悊鍒嗛〉鐨勭嚎绋嬪彉閲�
+     */
+    public static void clearPage()
+    {
+        PageHelper.clearPage();
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/utils/SecurityUtils.java b/jcdm-common/src/main/java/com/jcdm/common/utils/SecurityUtils.java
new file mode 100644
index 0000000..b05349d
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/utils/SecurityUtils.java
@@ -0,0 +1,178 @@
+package com.jcdm.common.utils;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.util.PatternMatchUtils;
+import com.jcdm.common.constant.Constants;
+import com.jcdm.common.constant.HttpStatus;
+import com.jcdm.common.core.domain.entity.SysRole;
+import com.jcdm.common.core.domain.model.LoginUser;
+import com.jcdm.common.exception.ServiceException;
+
+/**
+ * 瀹夊叏鏈嶅姟宸ュ叿绫�
+ * 
+ * @author jc
+ */
+public class SecurityUtils
+{
+
+    /**
+     * 鐢ㄦ埛ID
+     **/
+    public static Long getUserId()
+    {
+        try
+        {
+            return getLoginUser().getUserId();
+        }
+        catch (Exception e)
+        {
+            throw new ServiceException("鑾峰彇鐢ㄦ埛ID寮傚父", HttpStatus.UNAUTHORIZED);
+        }
+    }
+
+    /**
+     * 鑾峰彇閮ㄩ棬ID
+     **/
+    public static Long getDeptId()
+    {
+        try
+        {
+            return getLoginUser().getDeptId();
+        }
+        catch (Exception e)
+        {
+            throw new ServiceException("鑾峰彇閮ㄩ棬ID寮傚父", HttpStatus.UNAUTHORIZED);
+        }
+    }
+
+    /**
+     * 鑾峰彇鐢ㄦ埛璐︽埛
+     **/
+    public static String getUsername()
+    {
+        try
+        {
+            return getLoginUser().getUsername();
+        }
+        catch (Exception e)
+        {
+            throw new ServiceException("鑾峰彇鐢ㄦ埛璐︽埛寮傚父", HttpStatus.UNAUTHORIZED);
+        }
+    }
+
+    /**
+     * 鑾峰彇鐢ㄦ埛
+     **/
+    public static LoginUser getLoginUser()
+    {
+        try
+        {
+            return (LoginUser) getAuthentication().getPrincipal();
+        }
+        catch (Exception e)
+        {
+            throw new ServiceException("鑾峰彇鐢ㄦ埛淇℃伅寮傚父", HttpStatus.UNAUTHORIZED);
+        }
+    }
+
+    /**
+     * 鑾峰彇Authentication
+     */
+    public static Authentication getAuthentication()
+    {
+        return SecurityContextHolder.getContext().getAuthentication();
+    }
+
+    /**
+     * 鐢熸垚BCryptPasswordEncoder瀵嗙爜
+     *
+     * @param password 瀵嗙爜
+     * @return 鍔犲瘑瀛楃涓�
+     */
+    public static String encryptPassword(String password)
+    {
+        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
+        return passwordEncoder.encode(password);
+    }
+
+    /**
+     * 鍒ゆ柇瀵嗙爜鏄惁鐩稿悓
+     *
+     * @param rawPassword 鐪熷疄瀵嗙爜
+     * @param encodedPassword 鍔犲瘑鍚庡瓧绗�
+     * @return 缁撴灉
+     */
+    public static boolean matchesPassword(String rawPassword, String encodedPassword)
+    {
+        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
+        return passwordEncoder.matches(rawPassword, encodedPassword);
+    }
+
+    /**
+     * 鏄惁涓虹鐞嗗憳
+     * 
+     * @param userId 鐢ㄦ埛ID
+     * @return 缁撴灉
+     */
+    public static boolean isAdmin(Long userId)
+    {
+        return userId != null && 1L == userId;
+    }
+
+    /**
+     * 楠岃瘉鐢ㄦ埛鏄惁鍏峰鏌愭潈闄�
+     * 
+     * @param permission 鏉冮檺瀛楃涓�
+     * @return 鐢ㄦ埛鏄惁鍏峰鏌愭潈闄�
+     */
+    public static boolean hasPermi(String permission)
+    {
+        return hasPermi(getLoginUser().getPermissions(), permission);
+    }
+
+    /**
+     * 鍒ゆ柇鏄惁鍖呭惈鏉冮檺
+     * 
+     * @param authorities 鏉冮檺鍒楄〃
+     * @param permission 鏉冮檺瀛楃涓�
+     * @return 鐢ㄦ埛鏄惁鍏峰鏌愭潈闄�
+     */
+    public static boolean hasPermi(Collection<String> authorities, String permission)
+    {
+        return authorities.stream().filter(StringUtils::hasText)
+                .anyMatch(x -> Constants.ALL_PERMISSION.equals(x) || PatternMatchUtils.simpleMatch(x, permission));
+    }
+
+    /**
+     * 楠岃瘉鐢ㄦ埛鏄惁鎷ユ湁鏌愪釜瑙掕壊
+     * 
+     * @param role 瑙掕壊鏍囪瘑
+     * @return 鐢ㄦ埛鏄惁鍏峰鏌愯鑹�
+     */
+    public static boolean hasRole(String role)
+    {
+        List<SysRole> roleList = getLoginUser().getUser().getRoles();
+        Collection<String> roles = roleList.stream().map(SysRole::getRoleKey).collect(Collectors.toSet());
+        return hasRole(roles, role);
+    }
+
+    /**
+     * 鍒ゆ柇鏄惁鍖呭惈瑙掕壊
+     * 
+     * @param roles 瑙掕壊鍒楄〃
+     * @param role 瑙掕壊
+     * @return 鐢ㄦ埛鏄惁鍏峰鏌愯鑹叉潈闄�
+     */
+    public static boolean hasRole(Collection<String> roles, String role)
+    {
+        return roles.stream().filter(StringUtils::hasText)
+                .anyMatch(x -> Constants.SUPER_ADMIN.equals(x) || PatternMatchUtils.simpleMatch(x, role));
+    }
+
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/utils/ServletUtils.java b/jcdm-common/src/main/java/com/jcdm/common/utils/ServletUtils.java
new file mode 100644
index 0000000..b791ba9
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/utils/ServletUtils.java
@@ -0,0 +1,218 @@
+package com.jcdm.common.utils;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import javax.servlet.ServletRequest;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+import com.jcdm.common.constant.Constants;
+import com.jcdm.common.core.text.Convert;
+
+/**
+ * 瀹㈡埛绔伐鍏风被
+ * 
+ * @author jc
+ */
+public class ServletUtils
+{
+    /**
+     * 鑾峰彇String鍙傛暟
+     */
+    public static String getParameter(String name)
+    {
+        return getRequest().getParameter(name);
+    }
+
+    /**
+     * 鑾峰彇String鍙傛暟
+     */
+    public static String getParameter(String name, String defaultValue)
+    {
+        return Convert.toStr(getRequest().getParameter(name), defaultValue);
+    }
+
+    /**
+     * 鑾峰彇Integer鍙傛暟
+     */
+    public static Integer getParameterToInt(String name)
+    {
+        return Convert.toInt(getRequest().getParameter(name));
+    }
+
+    /**
+     * 鑾峰彇Integer鍙傛暟
+     */
+    public static Integer getParameterToInt(String name, Integer defaultValue)
+    {
+        return Convert.toInt(getRequest().getParameter(name), defaultValue);
+    }
+
+    /**
+     * 鑾峰彇Boolean鍙傛暟
+     */
+    public static Boolean getParameterToBool(String name)
+    {
+        return Convert.toBool(getRequest().getParameter(name));
+    }
+
+    /**
+     * 鑾峰彇Boolean鍙傛暟
+     */
+    public static Boolean getParameterToBool(String name, Boolean defaultValue)
+    {
+        return Convert.toBool(getRequest().getParameter(name), defaultValue);
+    }
+
+    /**
+     * 鑾峰緱鎵�鏈夎姹傚弬鏁�
+     *
+     * @param request 璇锋眰瀵硅薄{@link ServletRequest}
+     * @return Map
+     */
+    public static Map<String, String[]> getParams(ServletRequest request)
+    {
+        final Map<String, String[]> map = request.getParameterMap();
+        return Collections.unmodifiableMap(map);
+    }
+
+    /**
+     * 鑾峰緱鎵�鏈夎姹傚弬鏁�
+     *
+     * @param request 璇锋眰瀵硅薄{@link ServletRequest}
+     * @return Map
+     */
+    public static Map<String, String> getParamMap(ServletRequest request)
+    {
+        Map<String, String> params = new HashMap<>();
+        for (Map.Entry<String, String[]> entry : getParams(request).entrySet())
+        {
+            params.put(entry.getKey(), StringUtils.join(entry.getValue(), ","));
+        }
+        return params;
+    }
+
+    /**
+     * 鑾峰彇request
+     */
+    public static HttpServletRequest getRequest()
+    {
+        return getRequestAttributes().getRequest();
+    }
+
+    /**
+     * 鑾峰彇response
+     */
+    public static HttpServletResponse getResponse()
+    {
+        return getRequestAttributes().getResponse();
+    }
+
+    /**
+     * 鑾峰彇session
+     */
+    public static HttpSession getSession()
+    {
+        return getRequest().getSession();
+    }
+
+    public static ServletRequestAttributes getRequestAttributes()
+    {
+        RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
+        return (ServletRequestAttributes) attributes;
+    }
+
+    /**
+     * 灏嗗瓧绗︿覆娓叉煋鍒板鎴风
+     * 
+     * @param response 娓叉煋瀵硅薄
+     * @param string 寰呮覆鏌撶殑瀛楃涓�
+     */
+    public static void renderString(HttpServletResponse response, String string)
+    {
+        try
+        {
+            response.setStatus(200);
+            response.setContentType("application/json");
+            response.setCharacterEncoding("utf-8");
+            response.getWriter().print(string);
+        }
+        catch (IOException e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 鏄惁鏄疉jax寮傛璇锋眰
+     * 
+     * @param request
+     */
+    public static boolean isAjaxRequest(HttpServletRequest request)
+    {
+        String accept = request.getHeader("accept");
+        if (accept != null && accept.contains("application/json"))
+        {
+            return true;
+        }
+
+        String xRequestedWith = request.getHeader("X-Requested-With");
+        if (xRequestedWith != null && xRequestedWith.contains("XMLHttpRequest"))
+        {
+            return true;
+        }
+
+        String uri = request.getRequestURI();
+        if (StringUtils.inStringIgnoreCase(uri, ".json", ".xml"))
+        {
+            return true;
+        }
+
+        String ajax = request.getParameter("__ajax");
+        return StringUtils.inStringIgnoreCase(ajax, "json", "xml");
+    }
+
+    /**
+     * 鍐呭缂栫爜
+     * 
+     * @param str 鍐呭
+     * @return 缂栫爜鍚庣殑鍐呭
+     */
+    public static String urlEncode(String str)
+    {
+        try
+        {
+            return URLEncoder.encode(str, Constants.UTF8);
+        }
+        catch (UnsupportedEncodingException e)
+        {
+            return StringUtils.EMPTY;
+        }
+    }
+
+    /**
+     * 鍐呭瑙g爜
+     * 
+     * @param str 鍐呭
+     * @return 瑙g爜鍚庣殑鍐呭
+     */
+    public static String urlDecode(String str)
+    {
+        try
+        {
+            return URLDecoder.decode(str, Constants.UTF8);
+        }
+        catch (UnsupportedEncodingException e)
+        {
+            return StringUtils.EMPTY;
+        }
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/utils/StringUtils.java b/jcdm-common/src/main/java/com/jcdm/common/utils/StringUtils.java
new file mode 100644
index 0000000..b0fb6e4
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/utils/StringUtils.java
@@ -0,0 +1,638 @@
+package com.jcdm.common.utils;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.springframework.util.AntPathMatcher;
+import com.jcdm.common.constant.Constants;
+import com.jcdm.common.core.text.StrFormatter;
+
+/**
+ * 瀛楃涓插伐鍏风被
+ * 
+ * @author jc
+ */
+public class StringUtils extends org.apache.commons.lang3.StringUtils
+{
+    /** 绌哄瓧绗︿覆 */
+    private static final String NULLSTR = "";
+
+    /** 涓嬪垝绾� */
+    private static final char SEPARATOR = '_';
+
+    /**
+     * 鑾峰彇鍙傛暟涓嶄负绌哄��
+     * 
+     * @param value defaultValue 瑕佸垽鏂殑value
+     * @return value 杩斿洖鍊�
+     */
+    public static <T> T nvl(T value, T defaultValue)
+    {
+        return value != null ? value : defaultValue;
+    }
+
+    /**
+     * * 鍒ゆ柇涓�涓狢ollection鏄惁涓虹┖锛� 鍖呭惈List锛孲et锛孮ueue
+     * 
+     * @param coll 瑕佸垽鏂殑Collection
+     * @return true锛氫负绌� false锛氶潪绌�
+     */
+    public static boolean isEmpty(Collection<?> coll)
+    {
+        return isNull(coll) || coll.isEmpty();
+    }
+
+    /**
+     * * 鍒ゆ柇涓�涓狢ollection鏄惁闈炵┖锛屽寘鍚獿ist锛孲et锛孮ueue
+     * 
+     * @param coll 瑕佸垽鏂殑Collection
+     * @return true锛氶潪绌� false锛氱┖
+     */
+    public static boolean isNotEmpty(Collection<?> coll)
+    {
+        return !isEmpty(coll);
+    }
+
+    /**
+     * * 鍒ゆ柇涓�涓璞℃暟缁勬槸鍚︿负绌�
+     * 
+     * @param objects 瑕佸垽鏂殑瀵硅薄鏁扮粍
+     ** @return true锛氫负绌� false锛氶潪绌�
+     */
+    public static boolean isEmpty(Object[] objects)
+    {
+        return isNull(objects) || (objects.length == 0);
+    }
+
+    /**
+     * * 鍒ゆ柇涓�涓璞℃暟缁勬槸鍚﹂潪绌�
+     * 
+     * @param objects 瑕佸垽鏂殑瀵硅薄鏁扮粍
+     * @return true锛氶潪绌� false锛氱┖
+     */
+    public static boolean isNotEmpty(Object[] objects)
+    {
+        return !isEmpty(objects);
+    }
+
+    /**
+     * * 鍒ゆ柇涓�涓狹ap鏄惁涓虹┖
+     * 
+     * @param map 瑕佸垽鏂殑Map
+     * @return true锛氫负绌� false锛氶潪绌�
+     */
+    public static boolean isEmpty(Map<?, ?> map)
+    {
+        return isNull(map) || map.isEmpty();
+    }
+
+    /**
+     * * 鍒ゆ柇涓�涓狹ap鏄惁涓虹┖
+     * 
+     * @param map 瑕佸垽鏂殑Map
+     * @return true锛氶潪绌� false锛氱┖
+     */
+    public static boolean isNotEmpty(Map<?, ?> map)
+    {
+        return !isEmpty(map);
+    }
+
+    /**
+     * * 鍒ゆ柇涓�涓瓧绗︿覆鏄惁涓虹┖涓�
+     * 
+     * @param str String
+     * @return true锛氫负绌� false锛氶潪绌�
+     */
+    public static boolean isEmpty(String str)
+    {
+        return isNull(str) || NULLSTR.equals(str.trim());
+    }
+
+    /**
+     * * 鍒ゆ柇涓�涓瓧绗︿覆鏄惁涓洪潪绌轰覆
+     * 
+     * @param str String
+     * @return true锛氶潪绌轰覆 false锛氱┖涓�
+     */
+    public static boolean isNotEmpty(String str)
+    {
+        return !isEmpty(str);
+    }
+
+    /**
+     * * 鍒ゆ柇涓�涓璞℃槸鍚︿负绌�
+     * 
+     * @param object Object
+     * @return true锛氫负绌� false锛氶潪绌�
+     */
+    public static boolean isNull(Object object)
+    {
+        return object == null;
+    }
+
+    /**
+     * * 鍒ゆ柇涓�涓璞℃槸鍚﹂潪绌�
+     * 
+     * @param object Object
+     * @return true锛氶潪绌� false锛氱┖
+     */
+    public static boolean isNotNull(Object object)
+    {
+        return !isNull(object);
+    }
+
+    /**
+     * * 鍒ゆ柇涓�涓璞℃槸鍚︽槸鏁扮粍绫诲瀷锛圝ava鍩烘湰鍨嬪埆鐨勬暟缁勶級
+     * 
+     * @param object 瀵硅薄
+     * @return true锛氭槸鏁扮粍 false锛氫笉鏄暟缁�
+     */
+    public static boolean isArray(Object object)
+    {
+        return isNotNull(object) && object.getClass().isArray();
+    }
+
+    /**
+     * 鍘荤┖鏍�
+     */
+    public static String trim(String str)
+    {
+        return (str == null ? "" : str.trim());
+    }
+
+    /**
+     * 鎴彇瀛楃涓�
+     * 
+     * @param str 瀛楃涓�
+     * @param start 寮�濮�
+     * @return 缁撴灉
+     */
+    public static String substring(final String str, int start)
+    {
+        if (str == null)
+        {
+            return NULLSTR;
+        }
+
+        if (start < 0)
+        {
+            start = str.length() + start;
+        }
+
+        if (start < 0)
+        {
+            start = 0;
+        }
+        if (start > str.length())
+        {
+            return NULLSTR;
+        }
+
+        return str.substring(start);
+    }
+
+    /**
+     * 鎴彇瀛楃涓�
+     * 
+     * @param str 瀛楃涓�
+     * @param start 寮�濮�
+     * @param end 缁撴潫
+     * @return 缁撴灉
+     */
+    public static String substring(final String str, int start, int end)
+    {
+        if (str == null)
+        {
+            return NULLSTR;
+        }
+
+        if (end < 0)
+        {
+            end = str.length() + end;
+        }
+        if (start < 0)
+        {
+            start = str.length() + start;
+        }
+
+        if (end > str.length())
+        {
+            end = str.length();
+        }
+
+        if (start > end)
+        {
+            return NULLSTR;
+        }
+
+        if (start < 0)
+        {
+            start = 0;
+        }
+        if (end < 0)
+        {
+            end = 0;
+        }
+
+        return str.substring(start, end);
+    }
+
+    /**
+     * 鍒ゆ柇鏄惁涓虹┖锛屽苟涓斾笉鏄┖鐧藉瓧绗�
+     * 
+     * @param str 瑕佸垽鏂殑value
+     * @return 缁撴灉
+     */
+    public static boolean hasText(String str)
+    {
+        return (str != null && !str.isEmpty() && containsText(str));
+    }
+
+    private static boolean containsText(CharSequence str)
+    {
+        int strLen = str.length();
+        for (int i = 0; i < strLen; i++)
+        {
+            if (!Character.isWhitespace(str.charAt(i)))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 鏍煎紡鍖栨枃鏈�, {} 琛ㄧず鍗犱綅绗�<br>
+     * 姝ゆ柟娉曞彧鏄畝鍗曞皢鍗犱綅绗� {} 鎸夌収椤哄簭鏇挎崲涓哄弬鏁�<br>
+     * 濡傛灉鎯宠緭鍑� {} 浣跨敤 \\杞箟 { 鍗冲彲锛屽鏋滄兂杈撳嚭 {} 涔嬪墠鐨� \ 浣跨敤鍙岃浆涔夌 \\\\ 鍗冲彲<br>
+     * 渚嬶細<br>
+     * 閫氬父浣跨敤锛歠ormat("this is {} for {}", "a", "b") -> this is a for b<br>
+     * 杞箟{}锛� format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
+     * 杞箟\锛� format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
+     * 
+     * @param template 鏂囨湰妯℃澘锛岃鏇挎崲鐨勯儴鍒嗙敤 {} 琛ㄧず
+     * @param params 鍙傛暟鍊�
+     * @return 鏍煎紡鍖栧悗鐨勬枃鏈�
+     */
+    public static String format(String template, Object... params)
+    {
+        if (isEmpty(params) || isEmpty(template))
+        {
+            return template;
+        }
+        return StrFormatter.format(template, params);
+    }
+
+    /**
+     * 鏄惁涓篽ttp(s)://寮�澶�
+     * 
+     * @param link 閾炬帴
+     * @return 缁撴灉
+     */
+    public static boolean ishttp(String link)
+    {
+        return StringUtils.startsWithAny(link, Constants.HTTP, Constants.HTTPS);
+    }
+
+    /**
+     * 瀛楃涓茶浆set
+     * 
+     * @param str 瀛楃涓�
+     * @param sep 鍒嗛殧绗�
+     * @return set闆嗗悎
+     */
+    public static final Set<String> str2Set(String str, String sep)
+    {
+        return new HashSet<String>(str2List(str, sep, true, false));
+    }
+
+    /**
+     * 瀛楃涓茶浆list
+     * 
+     * @param str 瀛楃涓�
+     * @param sep 鍒嗛殧绗�
+     * @param filterBlank 杩囨护绾┖鐧�
+     * @param trim 鍘绘帀棣栧熬绌虹櫧
+     * @return list闆嗗悎
+     */
+    public static final List<String> str2List(String str, String sep, boolean filterBlank, boolean trim)
+    {
+        List<String> list = new ArrayList<String>();
+        if (StringUtils.isEmpty(str))
+        {
+            return list;
+        }
+
+        // 杩囨护绌虹櫧瀛楃涓�
+        if (filterBlank && StringUtils.isBlank(str))
+        {
+            return list;
+        }
+        String[] split = str.split(sep);
+        for (String string : split)
+        {
+            if (filterBlank && StringUtils.isBlank(string))
+            {
+                continue;
+            }
+            if (trim)
+            {
+                string = string.trim();
+            }
+            list.add(string);
+        }
+
+        return list;
+    }
+
+    /**
+     * 鍒ゆ柇缁欏畾鐨刢ollection鍒楄〃涓槸鍚﹀寘鍚暟缁刟rray 鍒ゆ柇缁欏畾鐨勬暟缁刟rray涓槸鍚﹀寘鍚粰瀹氱殑鍏冪礌value
+     *
+     * @param collection 缁欏畾鐨勯泦鍚�
+     * @param array 缁欏畾鐨勬暟缁�
+     * @return boolean 缁撴灉
+     */
+    public static boolean containsAny(Collection<String> collection, String... array)
+    {
+        if (isEmpty(collection) || isEmpty(array))
+        {
+            return false;
+        }
+        else
+        {
+            for (String str : array)
+            {
+                if (collection.contains(str))
+                {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
+    /**
+     * 鏌ユ壘鎸囧畾瀛楃涓叉槸鍚﹀寘鍚寚瀹氬瓧绗︿覆鍒楄〃涓殑浠绘剰涓�涓瓧绗︿覆鍚屾椂涓插拷鐣ュぇ灏忓啓
+     *
+     * @param cs 鎸囧畾瀛楃涓�
+     * @param searchCharSequences 闇�瑕佹鏌ョ殑瀛楃涓叉暟缁�
+     * @return 鏄惁鍖呭惈浠绘剰涓�涓瓧绗︿覆
+     */
+    public static boolean containsAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences)
+    {
+        if (isEmpty(cs) || isEmpty(searchCharSequences))
+        {
+            return false;
+        }
+        for (CharSequence testStr : searchCharSequences)
+        {
+            if (containsIgnoreCase(cs, testStr))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 椹煎嘲杞笅鍒掔嚎鍛藉悕
+     */
+    public static String toUnderScoreCase(String str)
+    {
+        if (str == null)
+        {
+            return null;
+        }
+        StringBuilder sb = new StringBuilder();
+        // 鍓嶇疆瀛楃鏄惁澶у啓
+        boolean preCharIsUpperCase = true;
+        // 褰撳墠瀛楃鏄惁澶у啓
+        boolean curreCharIsUpperCase = true;
+        // 涓嬩竴瀛楃鏄惁澶у啓
+        boolean nexteCharIsUpperCase = true;
+        for (int i = 0; i < str.length(); i++)
+        {
+            char c = str.charAt(i);
+            if (i > 0)
+            {
+                preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1));
+            }
+            else
+            {
+                preCharIsUpperCase = false;
+            }
+
+            curreCharIsUpperCase = Character.isUpperCase(c);
+
+            if (i < (str.length() - 1))
+            {
+                nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
+            }
+
+            if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase)
+            {
+                sb.append(SEPARATOR);
+            }
+            else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase)
+            {
+                sb.append(SEPARATOR);
+            }
+            sb.append(Character.toLowerCase(c));
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * 鏄惁鍖呭惈瀛楃涓�
+     * 
+     * @param str 楠岃瘉瀛楃涓�
+     * @param strs 瀛楃涓茬粍
+     * @return 鍖呭惈杩斿洖true
+     */
+    public static boolean inStringIgnoreCase(String str, String... strs)
+    {
+        if (str != null && strs != null)
+        {
+            for (String s : strs)
+            {
+                if (str.equalsIgnoreCase(trim(s)))
+                {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 灏嗕笅鍒掔嚎澶у啓鏂瑰紡鍛藉悕鐨勫瓧绗︿覆杞崲涓洪┘宄板紡銆傚鏋滆浆鎹㈠墠鐨勪笅鍒掔嚎澶у啓鏂瑰紡鍛藉悕鐨勫瓧绗︿覆涓虹┖锛屽垯杩斿洖绌哄瓧绗︿覆銆� 渚嬪锛欻ELLO_WORLD->HelloWorld
+     * 
+     * @param name 杞崲鍓嶇殑涓嬪垝绾垮ぇ鍐欐柟寮忓懡鍚嶇殑瀛楃涓�
+     * @return 杞崲鍚庣殑椹煎嘲寮忓懡鍚嶇殑瀛楃涓�
+     */
+    public static String convertToCamelCase(String name)
+    {
+        StringBuilder result = new StringBuilder();
+        // 蹇�熸鏌�
+        if (name == null || name.isEmpty())
+        {
+            // 娌″繀瑕佽浆鎹�
+            return "";
+        }
+        else if (!name.contains("_"))
+        {
+            // 涓嶅惈涓嬪垝绾匡紝浠呭皢棣栧瓧姣嶅ぇ鍐�
+            return name.substring(0, 1).toUpperCase() + name.substring(1);
+        }
+        // 鐢ㄤ笅鍒掔嚎灏嗗師濮嬪瓧绗︿覆鍒嗗壊
+        String[] camels = name.split("_");
+        for (String camel : camels)
+        {
+            // 璺宠繃鍘熷瀛楃涓蹭腑寮�澶淬�佺粨灏剧殑涓嬫崲绾挎垨鍙岄噸涓嬪垝绾�
+            if (camel.isEmpty())
+            {
+                continue;
+            }
+            // 棣栧瓧姣嶅ぇ鍐�
+            result.append(camel.substring(0, 1).toUpperCase());
+            result.append(camel.substring(1).toLowerCase());
+        }
+        return result.toString();
+    }
+
+    /**
+     * 椹煎嘲寮忓懡鍚嶆硶
+     * 渚嬪锛歶ser_name->userName
+     */
+    public static String toCamelCase(String s)
+    {
+        if (s == null)
+        {
+            return null;
+        }
+        if (s.indexOf(SEPARATOR) == -1)
+        {
+            return s;
+        }
+        s = s.toLowerCase();
+        StringBuilder sb = new StringBuilder(s.length());
+        boolean upperCase = false;
+        for (int i = 0; i < s.length(); i++)
+        {
+            char c = s.charAt(i);
+
+            if (c == SEPARATOR)
+            {
+                upperCase = true;
+            }
+            else if (upperCase)
+            {
+                sb.append(Character.toUpperCase(c));
+                upperCase = false;
+            }
+            else
+            {
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 鏌ユ壘鎸囧畾瀛楃涓叉槸鍚﹀尮閰嶆寚瀹氬瓧绗︿覆鍒楄〃涓殑浠绘剰涓�涓瓧绗︿覆
+     * 
+     * @param str 鎸囧畾瀛楃涓�
+     * @param strs 闇�瑕佹鏌ョ殑瀛楃涓叉暟缁�
+     * @return 鏄惁鍖归厤
+     */
+    public static boolean matches(String str, List<String> strs)
+    {
+        if (isEmpty(str) || isEmpty(strs))
+        {
+            return false;
+        }
+        for (String pattern : strs)
+        {
+            if (isMatch(pattern, str))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 鍒ゆ柇url鏄惁涓庤鍒欓厤缃�: 
+     * ? 琛ㄧず鍗曚釜瀛楃; 
+     * * 琛ㄧず涓�灞傝矾寰勫唴鐨勪换鎰忓瓧绗︿覆锛屼笉鍙法灞傜骇; 
+     * ** 琛ㄧず浠绘剰灞傝矾寰�;
+     * 
+     * @param pattern 鍖归厤瑙勫垯
+     * @param url 闇�瑕佸尮閰嶇殑url
+     * @return
+     */
+    public static boolean isMatch(String pattern, String url)
+    {
+        AntPathMatcher matcher = new AntPathMatcher();
+        return matcher.match(pattern, url);
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T> T cast(Object obj)
+    {
+        return (T) obj;
+    }
+
+    /**
+     * 鏁板瓧宸﹁竟琛ラ綈0锛屼娇涔嬭揪鍒版寚瀹氶暱搴︺�傛敞鎰忥紝濡傛灉鏁板瓧杞崲涓哄瓧绗︿覆鍚庯紝闀垮害澶т簬size锛屽垯鍙繚鐣� 鏈�鍚巗ize涓瓧绗︺��
+     * 
+     * @param num 鏁板瓧瀵硅薄
+     * @param size 瀛楃涓叉寚瀹氶暱搴�
+     * @return 杩斿洖鏁板瓧鐨勫瓧绗︿覆鏍煎紡锛岃瀛楃涓蹭负鎸囧畾闀垮害銆�
+     */
+    public static final String padl(final Number num, final int size)
+    {
+        return padl(num.toString(), size, '0');
+    }
+
+    /**
+     * 瀛楃涓插乏琛ラ綈銆傚鏋滃師濮嬪瓧绗︿覆s闀垮害澶т簬size锛屽垯鍙繚鐣欐渶鍚巗ize涓瓧绗︺��
+     * 
+     * @param s 鍘熷瀛楃涓�
+     * @param size 瀛楃涓叉寚瀹氶暱搴�
+     * @param c 鐢ㄤ簬琛ラ綈鐨勫瓧绗�
+     * @return 杩斿洖鎸囧畾闀垮害鐨勫瓧绗︿覆锛岀敱鍘熷瓧绗︿覆宸﹁ˉ榻愭垨鎴彇寰楀埌銆�
+     */
+    public static final String padl(final String s, final int size, final char c)
+    {
+        final StringBuilder sb = new StringBuilder(size);
+        if (s != null)
+        {
+            final int len = s.length();
+            if (s.length() <= size)
+            {
+                for (int i = size - len; i > 0; i--)
+                {
+                    sb.append(c);
+                }
+                sb.append(s);
+            }
+            else
+            {
+                return s.substring(len - size, len);
+            }
+        }
+        else
+        {
+            for (int i = size; i > 0; i--)
+            {
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
+}
\ No newline at end of file
diff --git a/jcdm-common/src/main/java/com/jcdm/common/utils/Threads.java b/jcdm-common/src/main/java/com/jcdm/common/utils/Threads.java
new file mode 100644
index 0000000..8405d5a
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/utils/Threads.java
@@ -0,0 +1,99 @@
+package com.jcdm.common.utils;
+
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 绾跨▼鐩稿叧宸ュ叿绫�.
+ * 
+ * @author jc
+ */
+public class Threads
+{
+    private static final Logger logger = LoggerFactory.getLogger(Threads.class);
+
+    /**
+     * sleep绛夊緟,鍗曚綅涓烘绉�
+     */
+    public static void sleep(long milliseconds)
+    {
+        try
+        {
+            Thread.sleep(milliseconds);
+        }
+        catch (InterruptedException e)
+        {
+            return;
+        }
+    }
+
+    /**
+     * 鍋滄绾跨▼姹�
+     * 鍏堜娇鐢╯hutdown, 鍋滄鎺ユ敹鏂颁换鍔″苟灏濊瘯瀹屾垚鎵�鏈夊凡瀛樺湪浠诲姟.
+     * 濡傛灉瓒呮椂, 鍒欒皟鐢╯hutdownNow, 鍙栨秷鍦╳orkQueue涓璓ending鐨勪换鍔�,骞朵腑鏂墍鏈夐樆濉炲嚱鏁�.
+     * 濡傛灉浠嶇劧瓒呮檪锛屽墖寮峰埗閫�鍑�.
+     * 鍙﹀鍦╯hutdown鏃剁嚎绋嬫湰韬璋冪敤涓柇鍋氫簡澶勭悊.
+     */
+    public static void shutdownAndAwaitTermination(ExecutorService pool)
+    {
+        if (pool != null && !pool.isShutdown())
+        {
+            pool.shutdown();
+            try
+            {
+                if (!pool.awaitTermination(120, TimeUnit.SECONDS))
+                {
+                    pool.shutdownNow();
+                    if (!pool.awaitTermination(120, TimeUnit.SECONDS))
+                    {
+                        logger.info("Pool did not terminate");
+                    }
+                }
+            }
+            catch (InterruptedException ie)
+            {
+                pool.shutdownNow();
+                Thread.currentThread().interrupt();
+            }
+        }
+    }
+
+    /**
+     * 鎵撳嵃绾跨▼寮傚父淇℃伅
+     */
+    public static void printException(Runnable r, Throwable t)
+    {
+        if (t == null && r instanceof Future<?>)
+        {
+            try
+            {
+                Future<?> future = (Future<?>) r;
+                if (future.isDone())
+                {
+                    future.get();
+                }
+            }
+            catch (CancellationException ce)
+            {
+                t = ce;
+            }
+            catch (ExecutionException ee)
+            {
+                t = ee.getCause();
+            }
+            catch (InterruptedException ie)
+            {
+                Thread.currentThread().interrupt();
+            }
+        }
+        if (t != null)
+        {
+            logger.error(t.getMessage(), t);
+        }
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/utils/bean/BeanUtils.java b/jcdm-common/src/main/java/com/jcdm/common/utils/bean/BeanUtils.java
new file mode 100644
index 0000000..cf9de54
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/utils/bean/BeanUtils.java
@@ -0,0 +1,110 @@
+package com.jcdm.common.utils.bean;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Bean 宸ュ叿绫�
+ * 
+ * @author jc
+ */
+public class BeanUtils extends org.springframework.beans.BeanUtils
+{
+    /** Bean鏂规硶鍚嶄腑灞炴�у悕寮�濮嬬殑涓嬫爣 */
+    private static final int BEAN_METHOD_PROP_INDEX = 3;
+
+    /** * 鍖归厤getter鏂规硶鐨勬鍒欒〃杈惧紡 */
+    private static final Pattern GET_PATTERN = Pattern.compile("get(\\p{javaUpperCase}\\w*)");
+
+    /** * 鍖归厤setter鏂规硶鐨勬鍒欒〃杈惧紡 */
+    private static final Pattern SET_PATTERN = Pattern.compile("set(\\p{javaUpperCase}\\w*)");
+
+    /**
+     * Bean灞炴�у鍒跺伐鍏锋柟娉曘��
+     * 
+     * @param dest 鐩爣瀵硅薄
+     * @param src 婧愬璞�
+     */
+    public static void copyBeanProp(Object dest, Object src)
+    {
+        try
+        {
+            copyProperties(src, dest);
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 鑾峰彇瀵硅薄鐨剆etter鏂规硶銆�
+     * 
+     * @param obj 瀵硅薄
+     * @return 瀵硅薄鐨剆etter鏂规硶鍒楄〃
+     */
+    public static List<Method> getSetterMethods(Object obj)
+    {
+        // setter鏂规硶鍒楄〃
+        List<Method> setterMethods = new ArrayList<Method>();
+
+        // 鑾峰彇鎵�鏈夋柟娉�
+        Method[] methods = obj.getClass().getMethods();
+
+        // 鏌ユ壘setter鏂规硶
+
+        for (Method method : methods)
+        {
+            Matcher m = SET_PATTERN.matcher(method.getName());
+            if (m.matches() && (method.getParameterTypes().length == 1))
+            {
+                setterMethods.add(method);
+            }
+        }
+        // 杩斿洖setter鏂规硶鍒楄〃
+        return setterMethods;
+    }
+
+    /**
+     * 鑾峰彇瀵硅薄鐨刧etter鏂规硶銆�
+     * 
+     * @param obj 瀵硅薄
+     * @return 瀵硅薄鐨刧etter鏂规硶鍒楄〃
+     */
+
+    public static List<Method> getGetterMethods(Object obj)
+    {
+        // getter鏂规硶鍒楄〃
+        List<Method> getterMethods = new ArrayList<Method>();
+        // 鑾峰彇鎵�鏈夋柟娉�
+        Method[] methods = obj.getClass().getMethods();
+        // 鏌ユ壘getter鏂规硶
+        for (Method method : methods)
+        {
+            Matcher m = GET_PATTERN.matcher(method.getName());
+            if (m.matches() && (method.getParameterTypes().length == 0))
+            {
+                getterMethods.add(method);
+            }
+        }
+        // 杩斿洖getter鏂规硶鍒楄〃
+        return getterMethods;
+    }
+
+    /**
+     * 妫�鏌ean鏂规硶鍚嶄腑鐨勫睘鎬у悕鏄惁鐩哥瓑銆�<br>
+     * 濡俫etName()鍜宻etName()灞炴�у悕涓�鏍凤紝getName()鍜宻etAge()灞炴�у悕涓嶄竴鏍枫��
+     * 
+     * @param m1 鏂规硶鍚�1
+     * @param m2 鏂规硶鍚�2
+     * @return 灞炴�у悕涓�鏍疯繑鍥瀟rue锛屽惁鍒欒繑鍥瀎alse
+     */
+
+    public static boolean isMethodPropEquals(String m1, String m2)
+    {
+        return m1.substring(BEAN_METHOD_PROP_INDEX).equals(m2.substring(BEAN_METHOD_PROP_INDEX));
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/utils/bean/BeanValidators.java b/jcdm-common/src/main/java/com/jcdm/common/utils/bean/BeanValidators.java
new file mode 100644
index 0000000..73acad0
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/utils/bean/BeanValidators.java
@@ -0,0 +1,24 @@
+package com.jcdm.common.utils.bean;
+
+import java.util.Set;
+import javax.validation.ConstraintViolation;
+import javax.validation.ConstraintViolationException;
+import javax.validation.Validator;
+
+/**
+ * bean瀵硅薄灞炴�ч獙璇�
+ * 
+ * @author jc
+ */
+public class BeanValidators
+{
+    public static void validateWithException(Validator validator, Object object, Class<?>... groups)
+            throws ConstraintViolationException
+    {
+        Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups);
+        if (!constraintViolations.isEmpty())
+        {
+            throw new ConstraintViolationException(constraintViolations);
+        }
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/utils/file/FileTypeUtils.java b/jcdm-common/src/main/java/com/jcdm/common/utils/file/FileTypeUtils.java
new file mode 100644
index 0000000..e928143
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/utils/file/FileTypeUtils.java
@@ -0,0 +1,76 @@
+package com.jcdm.common.utils.file;
+
+import java.io.File;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * 鏂囦欢绫诲瀷宸ュ叿绫�
+ *
+ * @author jc
+ */
+public class FileTypeUtils
+{
+    /**
+     * 鑾峰彇鏂囦欢绫诲瀷
+     * <p>
+     * 渚嬪: jcdm.txt, 杩斿洖: txt
+     * 
+     * @param file 鏂囦欢鍚�
+     * @return 鍚庣紑锛堜笉鍚�".")
+     */
+    public static String getFileType(File file)
+    {
+        if (null == file)
+        {
+            return StringUtils.EMPTY;
+        }
+        return getFileType(file.getName());
+    }
+
+    /**
+     * 鑾峰彇鏂囦欢绫诲瀷
+     * <p>
+     * 渚嬪: jcdm.txt, 杩斿洖: txt
+     *
+     * @param fileName 鏂囦欢鍚�
+     * @return 鍚庣紑锛堜笉鍚�".")
+     */
+    public static String getFileType(String fileName)
+    {
+        int separatorIndex = fileName.lastIndexOf(".");
+        if (separatorIndex < 0)
+        {
+            return "";
+        }
+        return fileName.substring(separatorIndex + 1).toLowerCase();
+    }
+
+    /**
+     * 鑾峰彇鏂囦欢绫诲瀷
+     * 
+     * @param photoByte 鏂囦欢瀛楄妭鐮�
+     * @return 鍚庣紑锛堜笉鍚�".")
+     */
+    public static String getFileExtendName(byte[] photoByte)
+    {
+        String strFileExtendName = "JPG";
+        if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56)
+                && ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97))
+        {
+            strFileExtendName = "GIF";
+        }
+        else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70))
+        {
+            strFileExtendName = "JPG";
+        }
+        else if ((photoByte[0] == 66) && (photoByte[1] == 77))
+        {
+            strFileExtendName = "BMP";
+        }
+        else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71))
+        {
+            strFileExtendName = "PNG";
+        }
+        return strFileExtendName;
+    }
+}
\ No newline at end of file
diff --git a/jcdm-common/src/main/java/com/jcdm/common/utils/file/FileUploadUtils.java b/jcdm-common/src/main/java/com/jcdm/common/utils/file/FileUploadUtils.java
new file mode 100644
index 0000000..67f1e03
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/utils/file/FileUploadUtils.java
@@ -0,0 +1,232 @@
+package com.jcdm.common.utils.file;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Paths;
+import java.util.Objects;
+import org.apache.commons.io.FilenameUtils;
+import org.springframework.web.multipart.MultipartFile;
+import com.jcdm.common.config.MesConfig;
+import com.jcdm.common.constant.Constants;
+import com.jcdm.common.exception.file.FileNameLengthLimitExceededException;
+import com.jcdm.common.exception.file.FileSizeLimitExceededException;
+import com.jcdm.common.exception.file.InvalidExtensionException;
+import com.jcdm.common.utils.DateUtils;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.common.utils.uuid.Seq;
+
+/**
+ * 鏂囦欢涓婁紶宸ュ叿绫�
+ *
+ * @author jc
+ */
+public class FileUploadUtils
+{
+    /**
+     * 榛樿澶у皬 50M
+     */
+    public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024;
+
+    /**
+     * 榛樿鐨勬枃浠跺悕鏈�澶ч暱搴� 100
+     */
+    public static final int DEFAULT_FILE_NAME_LENGTH = 100;
+
+    /**
+     * 榛樿涓婁紶鐨勫湴鍧�
+     */
+    private static String defaultBaseDir = MesConfig.getProfile();
+
+    public static void setDefaultBaseDir(String defaultBaseDir)
+    {
+        FileUploadUtils.defaultBaseDir = defaultBaseDir;
+    }
+
+    public static String getDefaultBaseDir()
+    {
+        return defaultBaseDir;
+    }
+
+    /**
+     * 浠ラ粯璁ら厤缃繘琛屾枃浠朵笂浼�
+     *
+     * @param file 涓婁紶鐨勬枃浠�
+     * @return 鏂囦欢鍚嶇О
+     * @throws Exception
+     */
+    public static final String upload(MultipartFile file) throws IOException
+    {
+        try
+        {
+            return upload(getDefaultBaseDir(), file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
+        }
+        catch (Exception e)
+        {
+            throw new IOException(e.getMessage(), e);
+        }
+    }
+
+    /**
+     * 鏍规嵁鏂囦欢璺緞涓婁紶
+     *
+     * @param baseDir 鐩稿搴旂敤鐨勫熀鐩綍
+     * @param file 涓婁紶鐨勬枃浠�
+     * @return 鏂囦欢鍚嶇О
+     * @throws IOException
+     */
+    public static final String upload(String baseDir, MultipartFile file) throws IOException
+    {
+        try
+        {
+            return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
+        }
+        catch (Exception e)
+        {
+            throw new IOException(e.getMessage(), e);
+        }
+    }
+
+    /**
+     * 鏂囦欢涓婁紶
+     *
+     * @param baseDir 鐩稿搴旂敤鐨勫熀鐩綍
+     * @param file 涓婁紶鐨勬枃浠�
+     * @param allowedExtension 涓婁紶鏂囦欢绫诲瀷
+     * @return 杩斿洖涓婁紶鎴愬姛鐨勬枃浠跺悕
+     * @throws FileSizeLimitExceededException 濡傛灉瓒呭嚭鏈�澶уぇ灏�
+     * @throws FileNameLengthLimitExceededException 鏂囦欢鍚嶅お闀�
+     * @throws IOException 姣斿璇诲啓鏂囦欢鍑洪敊鏃�
+     * @throws InvalidExtensionException 鏂囦欢鏍¢獙寮傚父
+     */
+    public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension)
+            throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
+            InvalidExtensionException
+    {
+        int fileNamelength = Objects.requireNonNull(file.getOriginalFilename()).length();
+        if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
+        {
+            throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
+        }
+
+        assertAllowed(file, allowedExtension);
+
+        String fileName = extractFilename(file);
+
+        String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
+        file.transferTo(Paths.get(absPath));
+        return getPathFileName(baseDir, fileName);
+    }
+
+    /**
+     * 缂栫爜鏂囦欢鍚�
+     */
+    public static final String extractFilename(MultipartFile file)
+    {
+        return StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(),
+                FilenameUtils.getBaseName(file.getOriginalFilename()), Seq.getId(Seq.uploadSeqType), getExtension(file));
+    }
+
+    public static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
+    {
+        File desc = new File(uploadDir + File.separator + fileName);
+
+        if (!desc.exists())
+        {
+            if (!desc.getParentFile().exists())
+            {
+                desc.getParentFile().mkdirs();
+            }
+        }
+        return desc;
+    }
+
+    public static final String getPathFileName(String uploadDir, String fileName) throws IOException
+    {
+        int dirLastIndex = MesConfig.getProfile().length() + 1;
+        String currentDir = StringUtils.substring(uploadDir, dirLastIndex);
+        return Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName;
+    }
+
+    /**
+     * 鏂囦欢澶у皬鏍¢獙
+     *
+     * @param file 涓婁紶鐨勬枃浠�
+     * @return
+     * @throws FileSizeLimitExceededException 濡傛灉瓒呭嚭鏈�澶уぇ灏�
+     * @throws InvalidExtensionException
+     */
+    public static final void assertAllowed(MultipartFile file, String[] allowedExtension)
+            throws FileSizeLimitExceededException, InvalidExtensionException
+    {
+        long size = file.getSize();
+        if (size > DEFAULT_MAX_SIZE)
+        {
+            throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024);
+        }
+
+        String fileName = file.getOriginalFilename();
+        String extension = getExtension(file);
+        if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension))
+        {
+            if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION)
+            {
+                throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
+                        fileName);
+            }
+            else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION)
+            {
+                throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,
+                        fileName);
+            }
+            else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION)
+            {
+                throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
+                        fileName);
+            }
+            else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION)
+            {
+                throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension,
+                        fileName);
+            }
+            else
+            {
+                throw new InvalidExtensionException(allowedExtension, extension, fileName);
+            }
+        }
+    }
+
+    /**
+     * 鍒ゆ柇MIME绫诲瀷鏄惁鏄厑璁哥殑MIME绫诲瀷
+     *
+     * @param extension
+     * @param allowedExtension
+     * @return
+     */
+    public static final boolean isAllowedExtension(String extension, String[] allowedExtension)
+    {
+        for (String str : allowedExtension)
+        {
+            if (str.equalsIgnoreCase(extension))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 鑾峰彇鏂囦欢鍚嶇殑鍚庣紑
+     *
+     * @param file 琛ㄥ崟鏂囦欢
+     * @return 鍚庣紑鍚�
+     */
+    public static final String getExtension(MultipartFile file)
+    {
+        String extension = FilenameUtils.getExtension(file.getOriginalFilename());
+        if (StringUtils.isEmpty(extension))
+        {
+            extension = MimeTypeUtils.getExtension(Objects.requireNonNull(file.getContentType()));
+        }
+        return extension;
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/utils/file/FileUtils.java b/jcdm-common/src/main/java/com/jcdm/common/utils/file/FileUtils.java
new file mode 100644
index 0000000..b9ed809
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/utils/file/FileUtils.java
@@ -0,0 +1,291 @@
+package com.jcdm.common.utils.file;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.ArrayUtils;
+import com.jcdm.common.config.MesConfig;
+import com.jcdm.common.utils.DateUtils;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.common.utils.uuid.IdUtils;
+import org.apache.commons.io.FilenameUtils;
+
+/**
+ * 鏂囦欢澶勭悊宸ュ叿绫�
+ * 
+ * @author jc
+ */
+public class FileUtils
+{
+    public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+";
+
+    /**
+     * 杈撳嚭鎸囧畾鏂囦欢鐨刡yte鏁扮粍
+     * 
+     * @param filePath 鏂囦欢璺緞
+     * @param os 杈撳嚭娴�
+     * @return
+     */
+    public static void writeBytes(String filePath, OutputStream os) throws IOException
+    {
+        FileInputStream fis = null;
+        try
+        {
+            File file = new File(filePath);
+            if (!file.exists())
+            {
+                throw new FileNotFoundException(filePath);
+            }
+            fis = new FileInputStream(file);
+            byte[] b = new byte[1024];
+            int length;
+            while ((length = fis.read(b)) > 0)
+            {
+                os.write(b, 0, length);
+            }
+        }
+        catch (IOException e)
+        {
+            throw e;
+        }
+        finally
+        {
+            IOUtils.close(os);
+            IOUtils.close(fis);
+        }
+    }
+
+    /**
+     * 鍐欐暟鎹埌鏂囦欢涓�
+     *
+     * @param data 鏁版嵁
+     * @return 鐩爣鏂囦欢
+     * @throws IOException IO寮傚父
+     */
+    public static String writeImportBytes(byte[] data) throws IOException
+    {
+        return writeBytes(data, MesConfig.getImportPath());
+    }
+
+    /**
+     * 鍐欐暟鎹埌鏂囦欢涓�
+     *
+     * @param data 鏁版嵁
+     * @param uploadDir 鐩爣鏂囦欢
+     * @return 鐩爣鏂囦欢
+     * @throws IOException IO寮傚父
+     */
+    public static String writeBytes(byte[] data, String uploadDir) throws IOException
+    {
+        FileOutputStream fos = null;
+        String pathName = "";
+        try
+        {
+            String extension = getFileExtendName(data);
+            pathName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension;
+            File file = FileUploadUtils.getAbsoluteFile(uploadDir, pathName);
+            fos = new FileOutputStream(file);
+            fos.write(data);
+        }
+        finally
+        {
+            IOUtils.close(fos);
+        }
+        return FileUploadUtils.getPathFileName(uploadDir, pathName);
+    }
+
+    /**
+     * 鍒犻櫎鏂囦欢
+     * 
+     * @param filePath 鏂囦欢
+     * @return
+     */
+    public static boolean deleteFile(String filePath)
+    {
+        boolean flag = false;
+        File file = new File(filePath);
+        // 璺緞涓烘枃浠朵笖涓嶄负绌哄垯杩涜鍒犻櫎
+        if (file.isFile() && file.exists())
+        {
+            flag = file.delete();
+        }
+        return flag;
+    }
+
+    /**
+     * 鏂囦欢鍚嶇О楠岃瘉
+     * 
+     * @param filename 鏂囦欢鍚嶇О
+     * @return true 姝e父 false 闈炴硶
+     */
+    public static boolean isValidFilename(String filename)
+    {
+        return filename.matches(FILENAME_PATTERN);
+    }
+
+    /**
+     * 妫�鏌ユ枃浠舵槸鍚﹀彲涓嬭浇
+     * 
+     * @param resource 闇�瑕佷笅杞界殑鏂囦欢
+     * @return true 姝e父 false 闈炴硶
+     */
+    public static boolean checkAllowDownload(String resource)
+    {
+        // 绂佹鐩綍涓婅烦绾у埆
+        if (StringUtils.contains(resource, ".."))
+        {
+            return false;
+        }
+
+        // 妫�鏌ュ厑璁镐笅杞界殑鏂囦欢瑙勫垯
+        if (ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource)))
+        {
+            return true;
+        }
+
+        // 涓嶅湪鍏佽涓嬭浇鐨勬枃浠惰鍒�
+        return false;
+    }
+
+    /**
+     * 涓嬭浇鏂囦欢鍚嶉噸鏂扮紪鐮�
+     * 
+     * @param request 璇锋眰瀵硅薄
+     * @param fileName 鏂囦欢鍚�
+     * @return 缂栫爜鍚庣殑鏂囦欢鍚�
+     */
+    public static String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException
+    {
+        final String agent = request.getHeader("USER-AGENT");
+        String filename = fileName;
+        if (agent.contains("MSIE"))
+        {
+            // IE娴忚鍣�
+            filename = URLEncoder.encode(filename, "utf-8");
+            filename = filename.replace("+", " ");
+        }
+        else if (agent.contains("Firefox"))
+        {
+            // 鐏嫄娴忚鍣�
+            filename = new String(fileName.getBytes(), "ISO8859-1");
+        }
+        else if (agent.contains("Chrome"))
+        {
+            // google娴忚鍣�
+            filename = URLEncoder.encode(filename, "utf-8");
+        }
+        else
+        {
+            // 鍏跺畠娴忚鍣�
+            filename = URLEncoder.encode(filename, "utf-8");
+        }
+        return filename;
+    }
+
+    /**
+     * 涓嬭浇鏂囦欢鍚嶉噸鏂扮紪鐮�
+     *
+     * @param response 鍝嶅簲瀵硅薄
+     * @param realFileName 鐪熷疄鏂囦欢鍚�
+     */
+    public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException
+    {
+        String percentEncodedFileName = percentEncode(realFileName);
+
+        StringBuilder contentDispositionValue = new StringBuilder();
+        contentDispositionValue.append("attachment; filename=")
+                .append(percentEncodedFileName)
+                .append(";")
+                .append("filename*=")
+                .append("utf-8''")
+                .append(percentEncodedFileName);
+
+        response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename");
+        response.setHeader("Content-disposition", contentDispositionValue.toString());
+        response.setHeader("download-filename", percentEncodedFileName);
+    }
+
+    /**
+     * 鐧惧垎鍙风紪鐮佸伐鍏锋柟娉�
+     *
+     * @param s 闇�瑕佺櫨鍒嗗彿缂栫爜鐨勫瓧绗︿覆
+     * @return 鐧惧垎鍙风紪鐮佸悗鐨勫瓧绗︿覆
+     */
+    public static String percentEncode(String s) throws UnsupportedEncodingException
+    {
+        String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
+        return encode.replaceAll("\\+", "%20");
+    }
+
+    /**
+     * 鑾峰彇鍥惧儚鍚庣紑
+     * 
+     * @param photoByte 鍥惧儚鏁版嵁
+     * @return 鍚庣紑鍚�
+     */
+    public static String getFileExtendName(byte[] photoByte)
+    {
+        String strFileExtendName = "jpg";
+        if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56)
+                && ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97))
+        {
+            strFileExtendName = "gif";
+        }
+        else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70))
+        {
+            strFileExtendName = "jpg";
+        }
+        else if ((photoByte[0] == 66) && (photoByte[1] == 77))
+        {
+            strFileExtendName = "bmp";
+        }
+        else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71))
+        {
+            strFileExtendName = "png";
+        }
+        return strFileExtendName;
+    }
+
+    /**
+     * 鑾峰彇鏂囦欢鍚嶇О /profile/upload/2022/04/16/jcdm.png
+     * 
+     * @param fileName 璺緞鍚嶇О
+     * @return 娌℃湁鏂囦欢璺緞鐨勫悕绉�
+     */
+    public static String getName(String fileName)
+    {
+        if (fileName == null)
+        {
+            return null;
+        }
+        int lastUnixPos = fileName.lastIndexOf('/');
+        int lastWindowsPos = fileName.lastIndexOf('\\');
+        int index = Math.max(lastUnixPos, lastWindowsPos);
+        return fileName.substring(index + 1);
+    }
+
+    /**
+     * 鑾峰彇涓嶅甫鍚庣紑鏂囦欢鍚嶇О /profile/upload/2022/04/16/jcdm.png
+     * 
+     * @param fileName 璺緞鍚嶇О
+     * @return 娌℃湁鏂囦欢璺緞鍜屽悗缂�鐨勫悕绉�
+     */
+    public static String getNameNotSuffix(String fileName)
+    {
+        if (fileName == null)
+        {
+            return null;
+        }
+        String baseName = FilenameUtils.getBaseName(fileName);
+        return baseName;
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/utils/file/ImageUtils.java b/jcdm-common/src/main/java/com/jcdm/common/utils/file/ImageUtils.java
new file mode 100644
index 0000000..4ef69f3
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/utils/file/ImageUtils.java
@@ -0,0 +1,98 @@
+package com.jcdm.common.utils.file;
+
+import java.io.ByteArrayInputStream;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Arrays;
+import org.apache.poi.util.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.jcdm.common.config.MesConfig;
+import com.jcdm.common.constant.Constants;
+import com.jcdm.common.utils.StringUtils;
+
+/**
+ * 鍥剧墖澶勭悊宸ュ叿绫�
+ *
+ * @author jc
+ */
+public class ImageUtils
+{
+    private static final Logger log = LoggerFactory.getLogger(ImageUtils.class);
+
+    public static byte[] getImage(String imagePath)
+    {
+        InputStream is = getFile(imagePath);
+        try
+        {
+            return IOUtils.toByteArray(is);
+        }
+        catch (Exception e)
+        {
+            log.error("鍥剧墖鍔犺浇寮傚父 {}", e);
+            return null;
+        }
+        finally
+        {
+            IOUtils.closeQuietly(is);
+        }
+    }
+
+    public static InputStream getFile(String imagePath)
+    {
+        try
+        {
+            byte[] result = readFile(imagePath);
+            result = Arrays.copyOf(result, result.length);
+            return new ByteArrayInputStream(result);
+        }
+        catch (Exception e)
+        {
+            log.error("鑾峰彇鍥剧墖寮傚父 {}", e);
+        }
+        return null;
+    }
+
+    /**
+     * 璇诲彇鏂囦欢涓哄瓧鑺傛暟鎹�
+     * 
+     * @param url 鍦板潃
+     * @return 瀛楄妭鏁版嵁
+     */
+    public static byte[] readFile(String url)
+    {
+        InputStream in = null;
+        try
+        {
+            if (url.startsWith("http"))
+            {
+                // 缃戠粶鍦板潃
+                URL urlObj = new URL(url);
+                URLConnection urlConnection = urlObj.openConnection();
+                urlConnection.setConnectTimeout(30 * 1000);
+                urlConnection.setReadTimeout(60 * 1000);
+                urlConnection.setDoInput(true);
+                in = urlConnection.getInputStream();
+            }
+            else
+            {
+                // 鏈満鍦板潃
+                String localPath = MesConfig.getProfile();
+                String downloadPath = localPath + StringUtils.substringAfter(url, Constants.RESOURCE_PREFIX);
+                in = new FileInputStream(downloadPath);
+            }
+            return IOUtils.toByteArray(in);
+        }
+        catch (Exception e)
+        {
+            log.error("鑾峰彇鏂囦欢璺緞寮傚父 {}", e);
+            return null;
+        }
+        finally
+        {
+            IOUtils.closeQuietly(in);
+        }
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/utils/file/MimeTypeUtils.java b/jcdm-common/src/main/java/com/jcdm/common/utils/file/MimeTypeUtils.java
new file mode 100644
index 0000000..77cb7a3
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/utils/file/MimeTypeUtils.java
@@ -0,0 +1,59 @@
+package com.jcdm.common.utils.file;
+
+/**
+ * 濯掍綋绫诲瀷宸ュ叿绫�
+ * 
+ * @author jc
+ */
+public class MimeTypeUtils
+{
+    public static final String IMAGE_PNG = "image/png";
+
+    public static final String IMAGE_JPG = "image/jpg";
+
+    public static final String IMAGE_JPEG = "image/jpeg";
+
+    public static final String IMAGE_BMP = "image/bmp";
+
+    public static final String IMAGE_GIF = "image/gif";
+    
+    public static final String[] IMAGE_EXTENSION = { "bmp", "gif", "jpg", "jpeg", "png" };
+
+    public static final String[] FLASH_EXTENSION = { "swf", "flv" };
+
+    public static final String[] MEDIA_EXTENSION = { "swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg",
+            "asf", "rm", "rmvb" };
+
+    public static final String[] VIDEO_EXTENSION = { "mp4", "avi", "rmvb" };
+
+    public static final String[] DEFAULT_ALLOWED_EXTENSION = {
+            // 鍥剧墖
+            "bmp", "gif", "jpg", "jpeg", "png",
+            // word excel powerpoint
+            "doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt",
+            // 鍘嬬缉鏂囦欢
+            "rar", "zip", "gz", "bz2",
+            // 瑙嗛鏍煎紡
+            "mp4", "avi", "rmvb",
+            // pdf
+            "pdf" };
+
+    public static String getExtension(String prefix)
+    {
+        switch (prefix)
+        {
+            case IMAGE_PNG:
+                return "png";
+            case IMAGE_JPG:
+                return "jpg";
+            case IMAGE_JPEG:
+                return "jpeg";
+            case IMAGE_BMP:
+                return "bmp";
+            case IMAGE_GIF:
+                return "gif";
+            default:
+                return "";
+        }
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/utils/html/EscapeUtil.java b/jcdm-common/src/main/java/com/jcdm/common/utils/html/EscapeUtil.java
new file mode 100644
index 0000000..f20770e
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/utils/html/EscapeUtil.java
@@ -0,0 +1,167 @@
+package com.jcdm.common.utils.html;
+
+import com.jcdm.common.utils.StringUtils;
+
+/**
+ * 杞箟鍜屽弽杞箟宸ュ叿绫�
+ * 
+ * @author jc
+ */
+public class EscapeUtil
+{
+    public static final String RE_HTML_MARK = "(<[^<]*?>)|(<[\\s]*?/[^<]*?>)|(<[^<]*?/[\\s]*?>)";
+
+    private static final char[][] TEXT = new char[64][];
+
+    static
+    {
+        for (int i = 0; i < 64; i++)
+        {
+            TEXT[i] = new char[] { (char) i };
+        }
+
+        // special HTML characters
+        TEXT['\''] = "&#039;".toCharArray(); // 鍗曞紩鍙�
+        TEXT['"'] = "&#34;".toCharArray(); // 鍙屽紩鍙�
+        TEXT['&'] = "&#38;".toCharArray(); // &绗�
+        TEXT['<'] = "&#60;".toCharArray(); // 灏忎簬鍙�
+        TEXT['>'] = "&#62;".toCharArray(); // 澶т簬鍙�
+    }
+
+    /**
+     * 杞箟鏂囨湰涓殑HTML瀛楃涓哄畨鍏ㄧ殑瀛楃
+     * 
+     * @param text 琚浆涔夌殑鏂囨湰
+     * @return 杞箟鍚庣殑鏂囨湰
+     */
+    public static String escape(String text)
+    {
+        return encode(text);
+    }
+
+    /**
+     * 杩樺師琚浆涔夌殑HTML鐗规畩瀛楃
+     * 
+     * @param content 鍖呭惈杞箟绗︾殑HTML鍐呭
+     * @return 杞崲鍚庣殑瀛楃涓�
+     */
+    public static String unescape(String content)
+    {
+        return decode(content);
+    }
+
+    /**
+     * 娓呴櫎鎵�鏈塇TML鏍囩锛屼絾鏄笉鍒犻櫎鏍囩鍐呯殑鍐呭
+     * 
+     * @param content 鏂囨湰
+     * @return 娓呴櫎鏍囩鍚庣殑鏂囨湰
+     */
+    public static String clean(String content)
+    {
+        return new HTMLFilter().filter(content);
+    }
+
+    /**
+     * Escape缂栫爜
+     * 
+     * @param text 琚紪鐮佺殑鏂囨湰
+     * @return 缂栫爜鍚庣殑瀛楃
+     */
+    private static String encode(String text)
+    {
+        if (StringUtils.isEmpty(text))
+        {
+            return StringUtils.EMPTY;
+        }
+
+        final StringBuilder tmp = new StringBuilder(text.length() * 6);
+        char c;
+        for (int i = 0; i < text.length(); i++)
+        {
+            c = text.charAt(i);
+            if (c < 256)
+            {
+                tmp.append("%");
+                if (c < 16)
+                {
+                    tmp.append("0");
+                }
+                tmp.append(Integer.toString(c, 16));
+            }
+            else
+            {
+                tmp.append("%u");
+                if (c <= 0xfff)
+                {
+                    // issue#I49JU8@Gitee
+                    tmp.append("0");
+                }
+                tmp.append(Integer.toString(c, 16));
+            }
+        }
+        return tmp.toString();
+    }
+
+    /**
+     * Escape瑙g爜
+     * 
+     * @param content 琚浆涔夌殑鍐呭
+     * @return 瑙g爜鍚庣殑瀛楃涓�
+     */
+    public static String decode(String content)
+    {
+        if (StringUtils.isEmpty(content))
+        {
+            return content;
+        }
+
+        StringBuilder tmp = new StringBuilder(content.length());
+        int lastPos = 0, pos = 0;
+        char ch;
+        while (lastPos < content.length())
+        {
+            pos = content.indexOf("%", lastPos);
+            if (pos == lastPos)
+            {
+                if (content.charAt(pos + 1) == 'u')
+                {
+                    ch = (char) Integer.parseInt(content.substring(pos + 2, pos + 6), 16);
+                    tmp.append(ch);
+                    lastPos = pos + 6;
+                }
+                else
+                {
+                    ch = (char) Integer.parseInt(content.substring(pos + 1, pos + 3), 16);
+                    tmp.append(ch);
+                    lastPos = pos + 3;
+                }
+            }
+            else
+            {
+                if (pos == -1)
+                {
+                    tmp.append(content.substring(lastPos));
+                    lastPos = content.length();
+                }
+                else
+                {
+                    tmp.append(content.substring(lastPos, pos));
+                    lastPos = pos;
+                }
+            }
+        }
+        return tmp.toString();
+    }
+
+    public static void main(String[] args)
+    {
+        String html = "<script>alert(1);</script>";
+        String escape = EscapeUtil.escape(html);
+        // String html = "<scr<script>ipt>alert(\"XSS\")</scr<script>ipt>";
+        // String html = "<123";
+        // String html = "123>";
+        System.out.println("clean: " + EscapeUtil.clean(html));
+        System.out.println("escape: " + escape);
+        System.out.println("unescape: " + EscapeUtil.unescape(escape));
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/utils/html/HTMLFilter.java b/jcdm-common/src/main/java/com/jcdm/common/utils/html/HTMLFilter.java
new file mode 100644
index 0000000..fae8dd6
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/utils/html/HTMLFilter.java
@@ -0,0 +1,570 @@
+package com.jcdm.common.utils.html;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * HTML杩囨护鍣紝鐢ㄤ簬鍘婚櫎XSS婕忔礊闅愭偅銆�
+ *
+ * @author jc
+ */
+public final class HTMLFilter
+{
+    /**
+     * regex flag union representing /si modifiers in php
+     **/
+    private static final int REGEX_FLAGS_SI = Pattern.CASE_INSENSITIVE | Pattern.DOTALL;
+    private static final Pattern P_COMMENTS = Pattern.compile("<!--(.*?)-->", Pattern.DOTALL);
+    private static final Pattern P_COMMENT = Pattern.compile("^!--(.*)--$", REGEX_FLAGS_SI);
+    private static final Pattern P_TAGS = Pattern.compile("<(.*?)>", Pattern.DOTALL);
+    private static final Pattern P_END_TAG = Pattern.compile("^/([a-z0-9]+)", REGEX_FLAGS_SI);
+    private static final Pattern P_START_TAG = Pattern.compile("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI);
+    private static final Pattern P_QUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI);
+    private static final Pattern P_UNQUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI);
+    private static final Pattern P_PROTOCOL = Pattern.compile("^([^:]+):", REGEX_FLAGS_SI);
+    private static final Pattern P_ENTITY = Pattern.compile("&#(\\d+);?");
+    private static final Pattern P_ENTITY_UNICODE = Pattern.compile("&#x([0-9a-f]+);?");
+    private static final Pattern P_ENCODE = Pattern.compile("%([0-9a-f]{2});?");
+    private static final Pattern P_VALID_ENTITIES = Pattern.compile("&([^&;]*)(?=(;|&|$))");
+    private static final Pattern P_VALID_QUOTES = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL);
+    private static final Pattern P_END_ARROW = Pattern.compile("^>");
+    private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)");
+    private static final Pattern P_XML_CONTENT = Pattern.compile("(^|>)([^<]*?)(?=>)");
+    private static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile("<([^>]*?)(?=<|$)");
+    private static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile("(^|>)([^<]*?)(?=>)");
+    private static final Pattern P_AMP = Pattern.compile("&");
+    private static final Pattern P_QUOTE = Pattern.compile("\"");
+    private static final Pattern P_LEFT_ARROW = Pattern.compile("<");
+    private static final Pattern P_RIGHT_ARROW = Pattern.compile(">");
+    private static final Pattern P_BOTH_ARROWS = Pattern.compile("<>");
+
+    // @xxx could grow large... maybe use sesat's ReferenceMap
+    private static final ConcurrentMap<String, Pattern> P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap<>();
+    private static final ConcurrentMap<String, Pattern> P_REMOVE_SELF_BLANKS = new ConcurrentHashMap<>();
+
+    /**
+     * set of allowed html elements, along with allowed attributes for each element
+     **/
+    private final Map<String, List<String>> vAllowed;
+    /**
+     * counts of open tags for each (allowable) html element
+     **/
+    private final Map<String, Integer> vTagCounts = new HashMap<>();
+
+    /**
+     * html elements which must always be self-closing (e.g. "<img />")
+     **/
+    private final String[] vSelfClosingTags;
+    /**
+     * html elements which must always have separate opening and closing tags (e.g. "<b></b>")
+     **/
+    private final String[] vNeedClosingTags;
+    /**
+     * set of disallowed html elements
+     **/
+    private final String[] vDisallowed;
+    /**
+     * attributes which should be checked for valid protocols
+     **/
+    private final String[] vProtocolAtts;
+    /**
+     * allowed protocols
+     **/
+    private final String[] vAllowedProtocols;
+    /**
+     * tags which should be removed if they contain no content (e.g. "<b></b>" or "<b />")
+     **/
+    private final String[] vRemoveBlanks;
+    /**
+     * entities allowed within html markup
+     **/
+    private final String[] vAllowedEntities;
+    /**
+     * flag determining whether comments are allowed in input String.
+     */
+    private final boolean stripComment;
+    private final boolean encodeQuotes;
+    /**
+     * flag determining whether to try to make tags when presented with "unbalanced" angle brackets (e.g. "<b text </b>"
+     * becomes "<b> text </b>"). If set to false, unbalanced angle brackets will be html escaped.
+     */
+    private final boolean alwaysMakeTags;
+
+    /**
+     * Default constructor.
+     */
+    public HTMLFilter()
+    {
+        vAllowed = new HashMap<>();
+
+        final ArrayList<String> a_atts = new ArrayList<>();
+        a_atts.add("href");
+        a_atts.add("target");
+        vAllowed.put("a", a_atts);
+
+        final ArrayList<String> img_atts = new ArrayList<>();
+        img_atts.add("src");
+        img_atts.add("width");
+        img_atts.add("height");
+        img_atts.add("alt");
+        vAllowed.put("img", img_atts);
+
+        final ArrayList<String> no_atts = new ArrayList<>();
+        vAllowed.put("b", no_atts);
+        vAllowed.put("strong", no_atts);
+        vAllowed.put("i", no_atts);
+        vAllowed.put("em", no_atts);
+
+        vSelfClosingTags = new String[] { "img" };
+        vNeedClosingTags = new String[] { "a", "b", "strong", "i", "em" };
+        vDisallowed = new String[] {};
+        vAllowedProtocols = new String[] { "http", "mailto", "https" }; // no ftp.
+        vProtocolAtts = new String[] { "src", "href" };
+        vRemoveBlanks = new String[] { "a", "b", "strong", "i", "em" };
+        vAllowedEntities = new String[] { "amp", "gt", "lt", "quot" };
+        stripComment = true;
+        encodeQuotes = true;
+        alwaysMakeTags = false;
+    }
+
+    /**
+     * Map-parameter configurable constructor.
+     *
+     * @param conf map containing configuration. keys match field names.
+     */
+    @SuppressWarnings("unchecked")
+    public HTMLFilter(final Map<String, Object> conf)
+    {
+
+        assert conf.containsKey("vAllowed") : "configuration requires vAllowed";
+        assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags";
+        assert conf.containsKey("vNeedClosingTags") : "configuration requires vNeedClosingTags";
+        assert conf.containsKey("vDisallowed") : "configuration requires vDisallowed";
+        assert conf.containsKey("vAllowedProtocols") : "configuration requires vAllowedProtocols";
+        assert conf.containsKey("vProtocolAtts") : "configuration requires vProtocolAtts";
+        assert conf.containsKey("vRemoveBlanks") : "configuration requires vRemoveBlanks";
+        assert conf.containsKey("vAllowedEntities") : "configuration requires vAllowedEntities";
+
+        vAllowed = Collections.unmodifiableMap((HashMap<String, List<String>>) conf.get("vAllowed"));
+        vSelfClosingTags = (String[]) conf.get("vSelfClosingTags");
+        vNeedClosingTags = (String[]) conf.get("vNeedClosingTags");
+        vDisallowed = (String[]) conf.get("vDisallowed");
+        vAllowedProtocols = (String[]) conf.get("vAllowedProtocols");
+        vProtocolAtts = (String[]) conf.get("vProtocolAtts");
+        vRemoveBlanks = (String[]) conf.get("vRemoveBlanks");
+        vAllowedEntities = (String[]) conf.get("vAllowedEntities");
+        stripComment = conf.containsKey("stripComment") ? (Boolean) conf.get("stripComment") : true;
+        encodeQuotes = conf.containsKey("encodeQuotes") ? (Boolean) conf.get("encodeQuotes") : true;
+        alwaysMakeTags = conf.containsKey("alwaysMakeTags") ? (Boolean) conf.get("alwaysMakeTags") : true;
+    }
+
+    private void reset()
+    {
+        vTagCounts.clear();
+    }
+
+    // ---------------------------------------------------------------
+    // my versions of some PHP library functions
+    public static String chr(final int decimal)
+    {
+        return String.valueOf((char) decimal);
+    }
+
+    public static String htmlSpecialChars(final String s)
+    {
+        String result = s;
+        result = regexReplace(P_AMP, "&amp;", result);
+        result = regexReplace(P_QUOTE, "&quot;", result);
+        result = regexReplace(P_LEFT_ARROW, "&lt;", result);
+        result = regexReplace(P_RIGHT_ARROW, "&gt;", result);
+        return result;
+    }
+
+    // ---------------------------------------------------------------
+
+    /**
+     * given a user submitted input String, filter out any invalid or restricted html.
+     *
+     * @param input text (i.e. submitted by a user) than may contain html
+     * @return "clean" version of input, with only valid, whitelisted html elements allowed
+     */
+    public String filter(final String input)
+    {
+        reset();
+        String s = input;
+
+        s = escapeComments(s);
+
+        s = balanceHTML(s);
+
+        s = checkTags(s);
+
+        s = processRemoveBlanks(s);
+
+        // s = validateEntities(s);
+
+        return s;
+    }
+
+    public boolean isAlwaysMakeTags()
+    {
+        return alwaysMakeTags;
+    }
+
+    public boolean isStripComments()
+    {
+        return stripComment;
+    }
+
+    private String escapeComments(final String s)
+    {
+        final Matcher m = P_COMMENTS.matcher(s);
+        final StringBuffer buf = new StringBuffer();
+        if (m.find())
+        {
+            final String match = m.group(1); // (.*?)
+            m.appendReplacement(buf, Matcher.quoteReplacement("<!--" + htmlSpecialChars(match) + "-->"));
+        }
+        m.appendTail(buf);
+
+        return buf.toString();
+    }
+
+    private String balanceHTML(String s)
+    {
+        if (alwaysMakeTags)
+        {
+            //
+            // try and form html
+            //
+            s = regexReplace(P_END_ARROW, "", s);
+            // 涓嶈拷鍔犵粨鏉熸爣绛�
+            s = regexReplace(P_BODY_TO_END, "<$1>", s);
+            s = regexReplace(P_XML_CONTENT, "$1<$2", s);
+
+        }
+        else
+        {
+            //
+            // escape stray brackets
+            //
+            s = regexReplace(P_STRAY_LEFT_ARROW, "&lt;$1", s);
+            s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2&gt;<", s);
+
+            //
+            // the last regexp causes '<>' entities to appear
+            // (we need to do a lookahead assertion so that the last bracket can
+            // be used in the next pass of the regexp)
+            //
+            s = regexReplace(P_BOTH_ARROWS, "", s);
+        }
+
+        return s;
+    }
+
+    private String checkTags(String s)
+    {
+        Matcher m = P_TAGS.matcher(s);
+
+        final StringBuffer buf = new StringBuffer();
+        while (m.find())
+        {
+            String replaceStr = m.group(1);
+            replaceStr = processTag(replaceStr);
+            m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr));
+        }
+        m.appendTail(buf);
+
+        // these get tallied in processTag
+        // (remember to reset before subsequent calls to filter method)
+        final StringBuilder sBuilder = new StringBuilder(buf.toString());
+        for (String key : vTagCounts.keySet())
+        {
+            for (int ii = 0; ii < vTagCounts.get(key); ii++)
+            {
+                sBuilder.append("</").append(key).append(">");
+            }
+        }
+        s = sBuilder.toString();
+
+        return s;
+    }
+
+    private String processRemoveBlanks(final String s)
+    {
+        String result = s;
+        for (String tag : vRemoveBlanks)
+        {
+            if (!P_REMOVE_PAIR_BLANKS.containsKey(tag))
+            {
+                P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?></" + tag + ">"));
+            }
+            result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result);
+            if (!P_REMOVE_SELF_BLANKS.containsKey(tag))
+            {
+                P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>"));
+            }
+            result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result);
+        }
+
+        return result;
+    }
+
+    private static String regexReplace(final Pattern regex_pattern, final String replacement, final String s)
+    {
+        Matcher m = regex_pattern.matcher(s);
+        return m.replaceAll(replacement);
+    }
+
+    private String processTag(final String s)
+    {
+        // ending tags
+        Matcher m = P_END_TAG.matcher(s);
+        if (m.find())
+        {
+            final String name = m.group(1).toLowerCase();
+            if (allowed(name))
+            {
+                if (!inArray(name, vSelfClosingTags))
+                {
+                    if (vTagCounts.containsKey(name))
+                    {
+                        vTagCounts.put(name, vTagCounts.get(name) - 1);
+                        return "</" + name + ">";
+                    }
+                }
+            }
+        }
+
+        // starting tags
+        m = P_START_TAG.matcher(s);
+        if (m.find())
+        {
+            final String name = m.group(1).toLowerCase();
+            final String body = m.group(2);
+            String ending = m.group(3);
+
+            // debug( "in a starting tag, name='" + name + "'; body='" + body + "'; ending='" + ending + "'" );
+            if (allowed(name))
+            {
+                final StringBuilder params = new StringBuilder();
+
+                final Matcher m2 = P_QUOTED_ATTRIBUTES.matcher(body);
+                final Matcher m3 = P_UNQUOTED_ATTRIBUTES.matcher(body);
+                final List<String> paramNames = new ArrayList<>();
+                final List<String> paramValues = new ArrayList<>();
+                while (m2.find())
+                {
+                    paramNames.add(m2.group(1)); // ([a-z0-9]+)
+                    paramValues.add(m2.group(3)); // (.*?)
+                }
+                while (m3.find())
+                {
+                    paramNames.add(m3.group(1)); // ([a-z0-9]+)
+                    paramValues.add(m3.group(3)); // ([^\"\\s']+)
+                }
+
+                String paramName, paramValue;
+                for (int ii = 0; ii < paramNames.size(); ii++)
+                {
+                    paramName = paramNames.get(ii).toLowerCase();
+                    paramValue = paramValues.get(ii);
+
+                    // debug( "paramName='" + paramName + "'" );
+                    // debug( "paramValue='" + paramValue + "'" );
+                    // debug( "allowed? " + vAllowed.get( name ).contains( paramName ) );
+
+                    if (allowedAttribute(name, paramName))
+                    {
+                        if (inArray(paramName, vProtocolAtts))
+                        {
+                            paramValue = processParamProtocol(paramValue);
+                        }
+                        params.append(' ').append(paramName).append("=\\\"").append(paramValue).append("\\\"");
+                    }
+                }
+
+                if (inArray(name, vSelfClosingTags))
+                {
+                    ending = " /";
+                }
+
+                if (inArray(name, vNeedClosingTags))
+                {
+                    ending = "";
+                }
+
+                if (ending == null || ending.length() < 1)
+                {
+                    if (vTagCounts.containsKey(name))
+                    {
+                        vTagCounts.put(name, vTagCounts.get(name) + 1);
+                    }
+                    else
+                    {
+                        vTagCounts.put(name, 1);
+                    }
+                }
+                else
+                {
+                    ending = " /";
+                }
+                return "<" + name + params + ending + ">";
+            }
+            else
+            {
+                return "";
+            }
+        }
+
+        // comments
+        m = P_COMMENT.matcher(s);
+        if (!stripComment && m.find())
+        {
+            return "<" + m.group() + ">";
+        }
+
+        return "";
+    }
+
+    private String processParamProtocol(String s)
+    {
+        s = decodeEntities(s);
+        final Matcher m = P_PROTOCOL.matcher(s);
+        if (m.find())
+        {
+            final String protocol = m.group(1);
+            if (!inArray(protocol, vAllowedProtocols))
+            {
+                // bad protocol, turn into local anchor link instead
+                s = "#" + s.substring(protocol.length() + 1);
+                if (s.startsWith("#//"))
+                {
+                    s = "#" + s.substring(3);
+                }
+            }
+        }
+
+        return s;
+    }
+
+    private String decodeEntities(String s)
+    {
+        StringBuffer buf = new StringBuffer();
+
+        Matcher m = P_ENTITY.matcher(s);
+        while (m.find())
+        {
+            final String match = m.group(1);
+            final int decimal = Integer.decode(match).intValue();
+            m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
+        }
+        m.appendTail(buf);
+        s = buf.toString();
+
+        buf = new StringBuffer();
+        m = P_ENTITY_UNICODE.matcher(s);
+        while (m.find())
+        {
+            final String match = m.group(1);
+            final int decimal = Integer.valueOf(match, 16).intValue();
+            m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
+        }
+        m.appendTail(buf);
+        s = buf.toString();
+
+        buf = new StringBuffer();
+        m = P_ENCODE.matcher(s);
+        while (m.find())
+        {
+            final String match = m.group(1);
+            final int decimal = Integer.valueOf(match, 16).intValue();
+            m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
+        }
+        m.appendTail(buf);
+        s = buf.toString();
+
+        s = validateEntities(s);
+        return s;
+    }
+
+    private String validateEntities(final String s)
+    {
+        StringBuffer buf = new StringBuffer();
+
+        // validate entities throughout the string
+        Matcher m = P_VALID_ENTITIES.matcher(s);
+        while (m.find())
+        {
+            final String one = m.group(1); // ([^&;]*)
+            final String two = m.group(2); // (?=(;|&|$))
+            m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two)));
+        }
+        m.appendTail(buf);
+
+        return encodeQuotes(buf.toString());
+    }
+
+    private String encodeQuotes(final String s)
+    {
+        if (encodeQuotes)
+        {
+            StringBuffer buf = new StringBuffer();
+            Matcher m = P_VALID_QUOTES.matcher(s);
+            while (m.find())
+            {
+                final String one = m.group(1); // (>|^)
+                final String two = m.group(2); // ([^<]+?)
+                final String three = m.group(3); // (<|$)
+                // 涓嶆浛鎹㈠弻寮曞彿涓�&quot;锛岄槻姝son鏍煎紡鏃犳晥 regexReplace(P_QUOTE, "&quot;", two)
+                m.appendReplacement(buf, Matcher.quoteReplacement(one + two + three));
+            }
+            m.appendTail(buf);
+            return buf.toString();
+        }
+        else
+        {
+            return s;
+        }
+    }
+
+    private String checkEntity(final String preamble, final String term)
+    {
+
+        return ";".equals(term) && isValidEntity(preamble) ? '&' + preamble : "&amp;" + preamble;
+    }
+
+    private boolean isValidEntity(final String entity)
+    {
+        return inArray(entity, vAllowedEntities);
+    }
+
+    private static boolean inArray(final String s, final String[] array)
+    {
+        for (String item : array)
+        {
+            if (item != null && item.equals(s))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean allowed(final String name)
+    {
+        return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed);
+    }
+
+    private boolean allowedAttribute(final String name, final String paramName)
+    {
+        return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName));
+    }
+}
\ No newline at end of file
diff --git a/jcdm-common/src/main/java/com/jcdm/common/utils/http/HttpHelper.java b/jcdm-common/src/main/java/com/jcdm/common/utils/http/HttpHelper.java
new file mode 100644
index 0000000..0c0005b
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/utils/http/HttpHelper.java
@@ -0,0 +1,55 @@
+package com.jcdm.common.utils.http;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import javax.servlet.ServletRequest;
+import org.apache.commons.lang3.exception.ExceptionUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 閫氱敤http宸ュ叿灏佽
+ * 
+ * @author jc
+ */
+public class HttpHelper
+{
+    private static final Logger LOGGER = LoggerFactory.getLogger(HttpHelper.class);
+
+    public static String getBodyString(ServletRequest request)
+    {
+        StringBuilder sb = new StringBuilder();
+        BufferedReader reader = null;
+        try (InputStream inputStream = request.getInputStream())
+        {
+            reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
+            String line = "";
+            while ((line = reader.readLine()) != null)
+            {
+                sb.append(line);
+            }
+        }
+        catch (IOException e)
+        {
+            LOGGER.warn("getBodyString鍑虹幇闂锛�");
+        }
+        finally
+        {
+            if (reader != null)
+            {
+                try
+                {
+                    reader.close();
+                }
+                catch (IOException e)
+                {
+                    LOGGER.error(ExceptionUtils.getMessage(e));
+                }
+            }
+        }
+        return sb.toString();
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/utils/http/HttpUtils.java b/jcdm-common/src/main/java/com/jcdm/common/utils/http/HttpUtils.java
new file mode 100644
index 0000000..8a07736
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/utils/http/HttpUtils.java
@@ -0,0 +1,274 @@
+package com.jcdm.common.utils.http;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.net.ConnectException;
+import java.net.SocketTimeoutException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.nio.charset.StandardCharsets;
+import java.security.cert.X509Certificate;
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.jcdm.common.constant.Constants;
+import com.jcdm.common.utils.StringUtils;
+
+/**
+ * 閫氱敤http鍙戦�佹柟娉�
+ * 
+ * @author jc
+ */
+public class HttpUtils
+{
+    private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);
+
+    /**
+     * 鍚戞寚瀹� URL 鍙戦�丟ET鏂规硶鐨勮姹�
+     *
+     * @param url 鍙戦�佽姹傜殑 URL
+     * @return 鎵�浠h〃杩滅▼璧勬簮鐨勫搷搴旂粨鏋�
+     */
+    public static String sendGet(String url)
+    {
+        return sendGet(url, StringUtils.EMPTY);
+    }
+
+    /**
+     * 鍚戞寚瀹� URL 鍙戦�丟ET鏂规硶鐨勮姹�
+     *
+     * @param url 鍙戦�佽姹傜殑 URL
+     * @param param 璇锋眰鍙傛暟锛岃姹傚弬鏁板簲璇ユ槸 name1=value1&name2=value2 鐨勫舰寮忋��
+     * @return 鎵�浠h〃杩滅▼璧勬簮鐨勫搷搴旂粨鏋�
+     */
+    public static String sendGet(String url, String param)
+    {
+        return sendGet(url, param, Constants.UTF8);
+    }
+
+    /**
+     * 鍚戞寚瀹� URL 鍙戦�丟ET鏂规硶鐨勮姹�
+     *
+     * @param url 鍙戦�佽姹傜殑 URL
+     * @param param 璇锋眰鍙傛暟锛岃姹傚弬鏁板簲璇ユ槸 name1=value1&name2=value2 鐨勫舰寮忋��
+     * @param contentType 缂栫爜绫诲瀷
+     * @return 鎵�浠h〃杩滅▼璧勬簮鐨勫搷搴旂粨鏋�
+     */
+    public static String sendGet(String url, String param, String contentType)
+    {
+        StringBuilder result = new StringBuilder();
+        BufferedReader in = null;
+        try
+        {
+            String urlNameString = StringUtils.isNotBlank(param) ? url + "?" + param : url;
+            log.info("sendGet - {}", urlNameString);
+            URL realUrl = new URL(urlNameString);
+            URLConnection connection = realUrl.openConnection();
+            connection.setRequestProperty("accept", "*/*");
+            connection.setRequestProperty("connection", "Keep-Alive");
+            connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
+            connection.connect();
+            in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType));
+            String line;
+            while ((line = in.readLine()) != null)
+            {
+                result.append(line);
+            }
+            log.info("recv - {}", result);
+        }
+        catch (ConnectException e)
+        {
+            log.error("璋冪敤HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e);
+        }
+        catch (SocketTimeoutException e)
+        {
+            log.error("璋冪敤HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e);
+        }
+        catch (IOException e)
+        {
+            log.error("璋冪敤HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e);
+        }
+        catch (Exception e)
+        {
+            log.error("璋冪敤HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e);
+        }
+        finally
+        {
+            try
+            {
+                if (in != null)
+                {
+                    in.close();
+                }
+            }
+            catch (Exception ex)
+            {
+                log.error("璋冪敤in.close Exception, url=" + url + ",param=" + param, ex);
+            }
+        }
+        return result.toString();
+    }
+
+    /**
+     * 鍚戞寚瀹� URL 鍙戦�丳OST鏂规硶鐨勮姹�
+     *
+     * @param url 鍙戦�佽姹傜殑 URL
+     * @param param 璇锋眰鍙傛暟锛岃姹傚弬鏁板簲璇ユ槸 name1=value1&name2=value2 鐨勫舰寮忋��
+     * @return 鎵�浠h〃杩滅▼璧勬簮鐨勫搷搴旂粨鏋�
+     */
+    public static String sendPost(String url, String param)
+    {
+        PrintWriter out = null;
+        BufferedReader in = null;
+        StringBuilder result = new StringBuilder();
+        try
+        {
+            log.info("sendPost - {}", url);
+            URL realUrl = new URL(url);
+            URLConnection conn = realUrl.openConnection();
+            conn.setRequestProperty("accept", "*/*");
+            conn.setRequestProperty("connection", "Keep-Alive");
+            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
+            conn.setRequestProperty("Accept-Charset", "utf-8");
+            conn.setRequestProperty("contentType", "utf-8");
+            conn.setDoOutput(true);
+            conn.setDoInput(true);
+            out = new PrintWriter(conn.getOutputStream());
+            out.print(param);
+            out.flush();
+            in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
+            String line;
+            while ((line = in.readLine()) != null)
+            {
+                result.append(line);
+            }
+            log.info("recv - {}", result);
+        }
+        catch (ConnectException e)
+        {
+            log.error("璋冪敤HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e);
+        }
+        catch (SocketTimeoutException e)
+        {
+            log.error("璋冪敤HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e);
+        }
+        catch (IOException e)
+        {
+            log.error("璋冪敤HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e);
+        }
+        catch (Exception e)
+        {
+            log.error("璋冪敤HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e);
+        }
+        finally
+        {
+            try
+            {
+                if (out != null)
+                {
+                    out.close();
+                }
+                if (in != null)
+                {
+                    in.close();
+                }
+            }
+            catch (IOException ex)
+            {
+                log.error("璋冪敤in.close Exception, url=" + url + ",param=" + param, ex);
+            }
+        }
+        return result.toString();
+    }
+
+    public static String sendSSLPost(String url, String param)
+    {
+        StringBuilder result = new StringBuilder();
+        String urlNameString = url + "?" + param;
+        try
+        {
+            log.info("sendSSLPost - {}", urlNameString);
+            SSLContext sc = SSLContext.getInstance("SSL");
+            sc.init(null, new TrustManager[] { new TrustAnyTrustManager() }, new java.security.SecureRandom());
+            URL console = new URL(urlNameString);
+            HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();
+            conn.setRequestProperty("accept", "*/*");
+            conn.setRequestProperty("connection", "Keep-Alive");
+            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
+            conn.setRequestProperty("Accept-Charset", "utf-8");
+            conn.setRequestProperty("contentType", "utf-8");
+            conn.setDoOutput(true);
+            conn.setDoInput(true);
+
+            conn.setSSLSocketFactory(sc.getSocketFactory());
+            conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
+            conn.connect();
+            InputStream is = conn.getInputStream();
+            BufferedReader br = new BufferedReader(new InputStreamReader(is));
+            String ret = "";
+            while ((ret = br.readLine()) != null)
+            {
+                if (ret != null && !"".equals(ret.trim()))
+                {
+                    result.append(new String(ret.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8));
+                }
+            }
+            log.info("recv - {}", result);
+            conn.disconnect();
+            br.close();
+        }
+        catch (ConnectException e)
+        {
+            log.error("璋冪敤HttpUtils.sendSSLPost ConnectException, url=" + url + ",param=" + param, e);
+        }
+        catch (SocketTimeoutException e)
+        {
+            log.error("璋冪敤HttpUtils.sendSSLPost SocketTimeoutException, url=" + url + ",param=" + param, e);
+        }
+        catch (IOException e)
+        {
+            log.error("璋冪敤HttpUtils.sendSSLPost IOException, url=" + url + ",param=" + param, e);
+        }
+        catch (Exception e)
+        {
+            log.error("璋冪敤HttpsUtil.sendSSLPost Exception, url=" + url + ",param=" + param, e);
+        }
+        return result.toString();
+    }
+
+    private static class TrustAnyTrustManager implements X509TrustManager
+    {
+        @Override
+        public void checkClientTrusted(X509Certificate[] chain, String authType)
+        {
+        }
+
+        @Override
+        public void checkServerTrusted(X509Certificate[] chain, String authType)
+        {
+        }
+
+        @Override
+        public X509Certificate[] getAcceptedIssuers()
+        {
+            return new X509Certificate[] {};
+        }
+    }
+
+    private static class TrustAnyHostnameVerifier implements HostnameVerifier
+    {
+        @Override
+        public boolean verify(String hostname, SSLSession session)
+        {
+            return true;
+        }
+    }
+}
\ No newline at end of file
diff --git a/jcdm-common/src/main/java/com/jcdm/common/utils/ip/AddressUtils.java b/jcdm-common/src/main/java/com/jcdm/common/utils/ip/AddressUtils.java
new file mode 100644
index 0000000..a678ab1
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/utils/ip/AddressUtils.java
@@ -0,0 +1,56 @@
+package com.jcdm.common.utils.ip;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import com.jcdm.common.config.MesConfig;
+import com.jcdm.common.constant.Constants;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.common.utils.http.HttpUtils;
+
+/**
+ * 鑾峰彇鍦板潃绫�
+ * 
+ * @author jc
+ */
+public class AddressUtils
+{
+    private static final Logger log = LoggerFactory.getLogger(AddressUtils.class);
+
+    // IP鍦板潃鏌ヨ
+    public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp";
+
+    // 鏈煡鍦板潃
+    public static final String UNKNOWN = "XX XX";
+
+    public static String getRealAddressByIP(String ip)
+    {
+        // 鍐呯綉涓嶆煡璇�
+        if (IpUtils.internalIp(ip))
+        {
+            return "鍐呯綉IP";
+        }
+        if (MesConfig.isAddressEnabled())
+        {
+            try
+            {
+                String rspStr = HttpUtils.sendGet(IP_URL, "ip=" + ip + "&json=true", Constants.GBK);
+                if (StringUtils.isEmpty(rspStr))
+                {
+                    log.error("鑾峰彇鍦扮悊浣嶇疆寮傚父 {}", ip);
+                    return UNKNOWN;
+                }
+                JSONObject obj = JSON.parseObject(rspStr);
+                String region = obj.getString("pro");
+                String city = obj.getString("city");
+                return String.format("%s %s", region, city);
+            }
+            catch (Exception e)
+            {
+                log.error("鑾峰彇鍦扮悊浣嶇疆寮傚父 {}", ip);
+            }
+        }
+        return UNKNOWN;
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/utils/ip/IpUtils.java b/jcdm-common/src/main/java/com/jcdm/common/utils/ip/IpUtils.java
new file mode 100644
index 0000000..eb58fe6
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/utils/ip/IpUtils.java
@@ -0,0 +1,382 @@
+package com.jcdm.common.utils.ip;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import javax.servlet.http.HttpServletRequest;
+import com.jcdm.common.utils.ServletUtils;
+import com.jcdm.common.utils.StringUtils;
+
+/**
+ * 鑾峰彇IP鏂规硶
+ * 
+ * @author jc
+ */
+public class IpUtils
+{
+    public final static String REGX_0_255 = "(25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]\\d|\\d)";
+    // 鍖归厤 ip
+    public final static String REGX_IP = "((" + REGX_0_255 + "\\.){3}" + REGX_0_255 + ")";
+    public final static String REGX_IP_WILDCARD = "(((\\*\\.){3}\\*)|(" + REGX_0_255 + "(\\.\\*){3})|(" + REGX_0_255 + "\\." + REGX_0_255 + ")(\\.\\*){2}" + "|((" + REGX_0_255 + "\\.){3}\\*))";
+    // 鍖归厤缃戞
+    public final static String REGX_IP_SEG = "(" + REGX_IP + "\\-" + REGX_IP + ")";
+
+    /**
+     * 鑾峰彇瀹㈡埛绔疘P
+     * 
+     * @return IP鍦板潃
+     */
+    public static String getIpAddr()
+    {
+        return getIpAddr(ServletUtils.getRequest());
+    }
+
+    /**
+     * 鑾峰彇瀹㈡埛绔疘P
+     * 
+     * @param request 璇锋眰瀵硅薄
+     * @return IP鍦板潃
+     */
+    public static String getIpAddr(HttpServletRequest request)
+    {
+        if (request == null)
+        {
+            return "unknown";
+        }
+        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("X-Forwarded-For");
+        }
+        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("X-Real-IP");
+        }
+
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
+        {
+            ip = request.getRemoteAddr();
+        }
+
+        return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : getMultistageReverseProxyIp(ip);
+    }
+
+    /**
+     * 妫�鏌ユ槸鍚︿负鍐呴儴IP鍦板潃
+     * 
+     * @param ip IP鍦板潃
+     * @return 缁撴灉
+     */
+    public static boolean internalIp(String ip)
+    {
+        byte[] addr = textToNumericFormatV4(ip);
+        return internalIp(addr) || "127.0.0.1".equals(ip);
+    }
+
+    /**
+     * 妫�鏌ユ槸鍚︿负鍐呴儴IP鍦板潃
+     * 
+     * @param addr byte鍦板潃
+     * @return 缁撴灉
+     */
+    private static boolean internalIp(byte[] addr)
+    {
+        if (StringUtils.isNull(addr) || addr.length < 2)
+        {
+            return true;
+        }
+        final byte b0 = addr[0];
+        final byte b1 = addr[1];
+        // 10.x.x.x/8
+        final byte SECTION_1 = 0x0A;
+        // 172.16.x.x/12
+        final byte SECTION_2 = (byte) 0xAC;
+        final byte SECTION_3 = (byte) 0x10;
+        final byte SECTION_4 = (byte) 0x1F;
+        // 192.168.x.x/16
+        final byte SECTION_5 = (byte) 0xC0;
+        final byte SECTION_6 = (byte) 0xA8;
+        switch (b0)
+        {
+            case SECTION_1:
+                return true;
+            case SECTION_2:
+                if (b1 >= SECTION_3 && b1 <= SECTION_4)
+                {
+                    return true;
+                }
+            case SECTION_5:
+                switch (b1)
+                {
+                    case SECTION_6:
+                        return true;
+                }
+            default:
+                return false;
+        }
+    }
+
+    /**
+     * 灏咺Pv4鍦板潃杞崲鎴愬瓧鑺�
+     * 
+     * @param text IPv4鍦板潃
+     * @return byte 瀛楄妭
+     */
+    public static byte[] textToNumericFormatV4(String text)
+    {
+        if (text.length() == 0)
+        {
+            return null;
+        }
+
+        byte[] bytes = new byte[4];
+        String[] elements = text.split("\\.", -1);
+        try
+        {
+            long l;
+            int i;
+            switch (elements.length)
+            {
+                case 1:
+                    l = Long.parseLong(elements[0]);
+                    if ((l < 0L) || (l > 4294967295L))
+                    {
+                        return null;
+                    }
+                    bytes[0] = (byte) (int) (l >> 24 & 0xFF);
+                    bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF);
+                    bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
+                    bytes[3] = (byte) (int) (l & 0xFF);
+                    break;
+                case 2:
+                    l = Integer.parseInt(elements[0]);
+                    if ((l < 0L) || (l > 255L))
+                    {
+                        return null;
+                    }
+                    bytes[0] = (byte) (int) (l & 0xFF);
+                    l = Integer.parseInt(elements[1]);
+                    if ((l < 0L) || (l > 16777215L))
+                    {
+                        return null;
+                    }
+                    bytes[1] = (byte) (int) (l >> 16 & 0xFF);
+                    bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
+                    bytes[3] = (byte) (int) (l & 0xFF);
+                    break;
+                case 3:
+                    for (i = 0; i < 2; ++i)
+                    {
+                        l = Integer.parseInt(elements[i]);
+                        if ((l < 0L) || (l > 255L))
+                        {
+                            return null;
+                        }
+                        bytes[i] = (byte) (int) (l & 0xFF);
+                    }
+                    l = Integer.parseInt(elements[2]);
+                    if ((l < 0L) || (l > 65535L))
+                    {
+                        return null;
+                    }
+                    bytes[2] = (byte) (int) (l >> 8 & 0xFF);
+                    bytes[3] = (byte) (int) (l & 0xFF);
+                    break;
+                case 4:
+                    for (i = 0; i < 4; ++i)
+                    {
+                        l = Integer.parseInt(elements[i]);
+                        if ((l < 0L) || (l > 255L))
+                        {
+                            return null;
+                        }
+                        bytes[i] = (byte) (int) (l & 0xFF);
+                    }
+                    break;
+                default:
+                    return null;
+            }
+        }
+        catch (NumberFormatException e)
+        {
+            return null;
+        }
+        return bytes;
+    }
+
+    /**
+     * 鑾峰彇IP鍦板潃
+     * 
+     * @return 鏈湴IP鍦板潃
+     */
+    public static String getHostIp()
+    {
+        try
+        {
+            return InetAddress.getLocalHost().getHostAddress();
+        }
+        catch (UnknownHostException e)
+        {
+        }
+        return "127.0.0.1";
+    }
+
+    /**
+     * 鑾峰彇涓绘満鍚�
+     * 
+     * @return 鏈湴涓绘満鍚�
+     */
+    public static String getHostName()
+    {
+        try
+        {
+            return InetAddress.getLocalHost().getHostName();
+        }
+        catch (UnknownHostException e)
+        {
+        }
+        return "鏈煡";
+    }
+
+    /**
+     * 浠庡绾у弽鍚戜唬鐞嗕腑鑾峰緱绗竴涓潪unknown IP鍦板潃
+     *
+     * @param ip 鑾峰緱鐨処P鍦板潃
+     * @return 绗竴涓潪unknown IP鍦板潃
+     */
+    public static String getMultistageReverseProxyIp(String ip)
+    {
+        // 澶氱骇鍙嶅悜浠g悊妫�娴�
+        if (ip != null && ip.indexOf(",") > 0)
+        {
+            final String[] ips = ip.trim().split(",");
+            for (String subIp : ips)
+            {
+                if (false == isUnknown(subIp))
+                {
+                    ip = subIp;
+                    break;
+                }
+            }
+        }
+        return StringUtils.substring(ip, 0, 255);
+    }
+
+    /**
+     * 妫�娴嬬粰瀹氬瓧绗︿覆鏄惁涓烘湭鐭ワ紝澶氱敤浜庢娴婬TTP璇锋眰鐩稿叧
+     *
+     * @param checkString 琚娴嬬殑瀛楃涓�
+     * @return 鏄惁鏈煡
+     */
+    public static boolean isUnknown(String checkString)
+    {
+        return StringUtils.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString);
+    }
+
+    /**
+     * 鏄惁涓篒P
+     */
+    public static boolean isIP(String ip)
+    {
+        return StringUtils.isNotBlank(ip) && ip.matches(REGX_IP);
+    }
+
+    /**
+     * 鏄惁涓篒P锛屾垨 *涓洪棿闅旂殑閫氶厤绗﹀湴鍧�
+     */
+    public static boolean isIpWildCard(String ip)
+    {
+        return StringUtils.isNotBlank(ip) && ip.matches(REGX_IP_WILDCARD);
+    }
+
+    /**
+     * 妫�娴嬪弬鏁版槸鍚﹀湪ip閫氶厤绗﹂噷
+     */
+    public static boolean ipIsInWildCardNoCheck(String ipWildCard, String ip)
+    {
+        String[] s1 = ipWildCard.split("\\.");
+        String[] s2 = ip.split("\\.");
+        boolean isMatchedSeg = true;
+        for (int i = 0; i < s1.length && !s1[i].equals("*"); i++)
+        {
+            if (!s1[i].equals(s2[i]))
+            {
+                isMatchedSeg = false;
+                break;
+            }
+        }
+        return isMatchedSeg;
+    }
+
+    /**
+     * 鏄惁涓虹壒瀹氭牸寮忓:鈥�10.10.10.1-10.10.10.99鈥濈殑ip娈靛瓧绗︿覆
+     */
+    public static boolean isIPSegment(String ipSeg)
+    {
+        return StringUtils.isNotBlank(ipSeg) && ipSeg.matches(REGX_IP_SEG);
+    }
+
+    /**
+     * 鍒ゆ柇ip鏄惁鍦ㄦ寚瀹氱綉娈典腑
+     */
+    public static boolean ipIsInNetNoCheck(String iparea, String ip)
+    {
+        int idx = iparea.indexOf('-');
+        String[] sips = iparea.substring(0, idx).split("\\.");
+        String[] sipe = iparea.substring(idx + 1).split("\\.");
+        String[] sipt = ip.split("\\.");
+        long ips = 0L, ipe = 0L, ipt = 0L;
+        for (int i = 0; i < 4; ++i)
+        {
+            ips = ips << 8 | Integer.parseInt(sips[i]);
+            ipe = ipe << 8 | Integer.parseInt(sipe[i]);
+            ipt = ipt << 8 | Integer.parseInt(sipt[i]);
+        }
+        if (ips > ipe)
+        {
+            long t = ips;
+            ips = ipe;
+            ipe = t;
+        }
+        return ips <= ipt && ipt <= ipe;
+    }
+
+    /**
+     * 鏍¢獙ip鏄惁绗﹀悎杩囨护涓茶鍒�
+     * 
+     * @param filter 杩囨护IP鍒楄〃,鏀寔鍚庣紑'*'閫氶厤,鏀寔缃戞濡�:`10.10.10.1-10.10.10.99`
+     * @param ip 鏍¢獙IP鍦板潃
+     * @return boolean 缁撴灉
+     */
+    public static boolean isMatchedIp(String filter, String ip)
+    {
+        if (StringUtils.isEmpty(filter) || StringUtils.isEmpty(ip))
+        {
+            return false;
+        }
+        String[] ips = filter.split(";");
+        for (String iStr : ips)
+        {
+            if (isIP(iStr) && iStr.equals(ip))
+            {
+                return true;
+            }
+            else if (isIpWildCard(iStr) && ipIsInWildCardNoCheck(iStr, ip))
+            {
+                return true;
+            }
+            else if (isIPSegment(iStr) && ipIsInNetNoCheck(iStr, ip))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+}
\ No newline at end of file
diff --git a/jcdm-common/src/main/java/com/jcdm/common/utils/poi/ExcelHandlerAdapter.java b/jcdm-common/src/main/java/com/jcdm/common/utils/poi/ExcelHandlerAdapter.java
new file mode 100644
index 0000000..0f327bb
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/utils/poi/ExcelHandlerAdapter.java
@@ -0,0 +1,24 @@
+package com.jcdm.common.utils.poi;
+
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Workbook;
+
+/**
+ * Excel鏁版嵁鏍煎紡澶勭悊閫傞厤鍣�
+ * 
+ * @author jc
+ */
+public interface ExcelHandlerAdapter
+{
+    /**
+     * 鏍煎紡鍖�
+     * 
+     * @param value 鍗曞厓鏍兼暟鎹��
+     * @param args excel娉ㄨВargs鍙傛暟缁�
+     * @param cell 鍗曞厓鏍煎璞�
+     * @param wb 宸ヤ綔绨垮璞�
+     *
+     * @return 澶勭悊鍚庣殑鍊�
+     */
+    Object format(Object value, String[] args, Cell cell, Workbook wb);
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/utils/poi/ExcelUtil.java b/jcdm-common/src/main/java/com/jcdm/common/utils/poi/ExcelUtil.java
new file mode 100644
index 0000000..96d4125
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/utils/poi/ExcelUtil.java
@@ -0,0 +1,1758 @@
+package com.jcdm.common.utils.poi;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.math.BigDecimal;
+import java.text.DecimalFormat;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.stream.Collectors;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.RegExUtils;
+import org.apache.commons.lang3.reflect.FieldUtils;
+import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
+import org.apache.poi.hssf.usermodel.HSSFPicture;
+import org.apache.poi.hssf.usermodel.HSSFPictureData;
+import org.apache.poi.hssf.usermodel.HSSFShape;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ooxml.POIXMLDocumentPart;
+import org.apache.poi.ss.usermodel.BorderStyle;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.CellType;
+import org.apache.poi.ss.usermodel.ClientAnchor;
+import org.apache.poi.ss.usermodel.DataValidation;
+import org.apache.poi.ss.usermodel.DataValidationConstraint;
+import org.apache.poi.ss.usermodel.DataValidationHelper;
+import org.apache.poi.ss.usermodel.DateUtil;
+import org.apache.poi.ss.usermodel.Drawing;
+import org.apache.poi.ss.usermodel.FillPatternType;
+import org.apache.poi.ss.usermodel.Font;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.apache.poi.ss.usermodel.IndexedColors;
+import org.apache.poi.ss.usermodel.Name;
+import org.apache.poi.ss.usermodel.PictureData;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.VerticalAlignment;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.usermodel.WorkbookFactory;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.ss.util.CellRangeAddressList;
+import org.apache.poi.util.IOUtils;
+import org.apache.poi.xssf.streaming.SXSSFWorkbook;
+import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
+import org.apache.poi.xssf.usermodel.XSSFDataValidation;
+import org.apache.poi.xssf.usermodel.XSSFDrawing;
+import org.apache.poi.xssf.usermodel.XSSFPicture;
+import org.apache.poi.xssf.usermodel.XSSFShape;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.annotation.Excel.ColumnType;
+import com.jcdm.common.annotation.Excel.Type;
+import com.jcdm.common.annotation.Excels;
+import com.jcdm.common.config.MesConfig;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.core.text.Convert;
+import com.jcdm.common.exception.UtilException;
+import com.jcdm.common.utils.DateUtils;
+import com.jcdm.common.utils.DictUtils;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.common.utils.file.FileTypeUtils;
+import com.jcdm.common.utils.file.FileUtils;
+import com.jcdm.common.utils.file.ImageUtils;
+import com.jcdm.common.utils.reflect.ReflectUtils;
+
+/**
+ * Excel鐩稿叧澶勭悊
+ * 
+ * @author jc
+ */
+public class ExcelUtil<T>
+{
+    private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class);
+
+    public static final String FORMULA_REGEX_STR = "=|-|\\+|@";
+
+    public static final String[] FORMULA_STR = { "=", "-", "+", "@" };
+
+    /**
+     * 鐢ㄤ簬dictType灞炴�ф暟鎹瓨鍌紝閬垮厤閲嶅鏌ョ紦瀛�
+     */
+    public Map<String, String> sysDictMap = new HashMap<String, String>();
+
+    /**
+     * Excel sheet鏈�澶ц鏁帮紝榛樿65536
+     */
+    public static final int sheetSize = 65536;
+
+    /**
+     * 宸ヤ綔琛ㄥ悕绉�
+     */
+    private String sheetName;
+
+    /**
+     * 瀵煎嚭绫诲瀷锛圗XPORT:瀵煎嚭鏁版嵁锛汭MPORT锛氬鍏ユā鏉匡級
+     */
+    private Type type;
+
+    /**
+     * 宸ヤ綔钖勫璞�
+     */
+    private Workbook wb;
+
+    /**
+     * 宸ヤ綔琛ㄥ璞�
+     */
+    private Sheet sheet;
+
+    /**
+     * 鏍峰紡鍒楄〃
+     */
+    private Map<String, CellStyle> styles;
+
+    /**
+     * 瀵煎叆瀵煎嚭鏁版嵁鍒楄〃
+     */
+    private List<T> list;
+
+    /**
+     * 娉ㄨВ鍒楄〃
+     */
+    private List<Object[]> fields;
+
+    /**
+     * 褰撳墠琛屽彿
+     */
+    private int rownum;
+
+    /**
+     * 鏍囬
+     */
+    private String title;
+
+    /**
+     * 鏈�澶ч珮搴�
+     */
+    private short maxHeight;
+
+    /**
+     * 鍚堝苟鍚庢渶鍚庤鏁�
+     */
+    private int subMergedLastRowNum = 0;
+
+    /**
+     * 鍚堝苟鍚庡紑濮嬭鏁�
+     */
+    private int subMergedFirstRowNum = 1;
+
+    /**
+     * 瀵硅薄鐨勫瓙鍒楄〃鏂规硶
+     */
+    private Method subMethod;
+
+    /**
+     * 瀵硅薄鐨勫瓙鍒楄〃灞炴��
+     */
+    private List<Field> subFields;
+
+    /**
+     * 缁熻鍒楄〃
+     */
+    private Map<Integer, Double> statistics = new HashMap<Integer, Double>();
+
+    /**
+     * 鏁板瓧鏍煎紡
+     */
+    private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00");
+
+    /**
+     * 瀹炰綋瀵硅薄
+     */
+    public Class<T> clazz;
+
+    /**
+     * 闇�瑕佹帓闄ゅ垪灞炴��
+     */
+    public String[] excludeFields;
+
+    public ExcelUtil(Class<T> clazz)
+    {
+        this.clazz = clazz;
+    }
+
+    /**
+     * 闅愯棌Excel涓垪灞炴��
+     *
+     * @param fields 鍒楀睘鎬у悕 绀轰緥[鍗曚釜"name"/澶氫釜"id","name"]
+     * @throws Exception
+     */
+    public void hideColumn(String... fields)
+    {
+        this.excludeFields = fields;
+    }
+
+    public void init(List<T> list, String sheetName, String title, Type type)
+    {
+        if (list == null)
+        {
+            list = new ArrayList<T>();
+        }
+        this.list = list;
+        this.sheetName = sheetName;
+        this.type = type;
+        this.title = title;
+        createExcelField();
+        createWorkbook();
+        createTitle();
+        createSubHead();
+    }
+
+    /**
+     * 鍒涘缓excel绗竴琛屾爣棰�
+     */
+    public void createTitle()
+    {
+        if (StringUtils.isNotEmpty(title))
+        {
+            subMergedFirstRowNum++;
+            subMergedLastRowNum++;
+            int titleLastCol = this.fields.size() - 1;
+            if (isSubList())
+            {
+                titleLastCol = titleLastCol + subFields.size() - 1;
+            }
+            Row titleRow = sheet.createRow(rownum == 0 ? rownum++ : 0);
+            titleRow.setHeightInPoints(30);
+            Cell titleCell = titleRow.createCell(0);
+            titleCell.setCellStyle(styles.get("title"));
+            titleCell.setCellValue(title);
+            sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), titleRow.getRowNum(), titleLastCol));
+        }
+    }
+
+    /**
+     * 鍒涘缓瀵硅薄鐨勫瓙鍒楄〃鍚嶇О
+     */
+    public void createSubHead()
+    {
+        if (isSubList())
+        {
+            subMergedFirstRowNum++;
+            subMergedLastRowNum++;
+            Row subRow = sheet.createRow(rownum);
+            int excelNum = 0;
+            for (Object[] objects : fields)
+            {
+                Excel attr = (Excel) objects[1];
+                Cell headCell1 = subRow.createCell(excelNum);
+                headCell1.setCellValue(attr.name());
+                headCell1.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));
+                excelNum++;
+            }
+            int headFirstRow = excelNum - 1;
+            int headLastRow = headFirstRow + subFields.size() - 1;
+            if (headLastRow > headFirstRow)
+            {
+                sheet.addMergedRegion(new CellRangeAddress(rownum, rownum, headFirstRow, headLastRow));
+            }
+            rownum++;
+        }
+    }
+
+    /**
+     * 瀵筫xcel琛ㄥ崟榛樿绗竴涓储寮曞悕杞崲鎴恖ist
+     * 
+     * @param is 杈撳叆娴�
+     * @return 杞崲鍚庨泦鍚�
+     */
+    public List<T> importExcel(InputStream is)
+    {
+        List<T> list = null;
+        try
+        {
+            list = importExcel(is, 0);
+        }
+        catch (Exception e)
+        {
+            log.error("瀵煎叆Excel寮傚父{}", e.getMessage());
+            throw new UtilException(e.getMessage());
+        }
+        finally
+        {
+            IOUtils.closeQuietly(is);
+        }
+        return list;
+    }
+
+    /**
+     * 瀵筫xcel琛ㄥ崟榛樿绗竴涓储寮曞悕杞崲鎴恖ist
+     * 
+     * @param is 杈撳叆娴�
+     * @param titleNum 鏍囬鍗犵敤琛屾暟
+     * @return 杞崲鍚庨泦鍚�
+     */
+    public List<T> importExcel(InputStream is, int titleNum) throws Exception
+    {
+        return importExcel(StringUtils.EMPTY, is, titleNum);
+    }
+
+    /**
+     * 瀵筫xcel琛ㄥ崟鎸囧畾琛ㄦ牸绱㈠紩鍚嶈浆鎹㈡垚list
+     * 
+     * @param sheetName 琛ㄦ牸绱㈠紩鍚�
+     * @param titleNum 鏍囬鍗犵敤琛屾暟
+     * @param is 杈撳叆娴�
+     * @return 杞崲鍚庨泦鍚�
+     */
+    public List<T> importExcel(String sheetName, InputStream is, int titleNum) throws Exception
+    {
+        this.type = Type.IMPORT;
+        this.wb = WorkbookFactory.create(is);
+        List<T> list = new ArrayList<T>();
+        // 濡傛灉鎸囧畾sheet鍚�,鍒欏彇鎸囧畾sheet涓殑鍐呭 鍚﹀垯榛樿鎸囧悜绗�1涓猻heet
+        Sheet sheet = StringUtils.isNotEmpty(sheetName) ? wb.getSheet(sheetName) : wb.getSheetAt(0);
+        if (sheet == null)
+        {
+            throw new IOException("鏂囦欢sheet涓嶅瓨鍦�");
+        }
+        boolean isXSSFWorkbook = !(wb instanceof HSSFWorkbook);
+        Map<String, PictureData> pictures;
+        if (isXSSFWorkbook)
+        {
+            pictures = getSheetPictures07((XSSFSheet) sheet, (XSSFWorkbook) wb);
+        }
+        else
+        {
+            pictures = getSheetPictures03((HSSFSheet) sheet, (HSSFWorkbook) wb);
+        }
+        // 鑾峰彇鏈�鍚庝竴涓潪绌鸿鐨勮涓嬫爣锛屾瘮濡傛�昏鏁颁负n锛屽垯杩斿洖鐨勪负n-1
+        int rows = sheet.getLastRowNum();
+        if (rows > 0)
+        {
+            // 瀹氫箟涓�涓猰ap鐢ㄤ簬瀛樻斁excel鍒楃殑搴忓彿鍜宖ield.
+            Map<String, Integer> cellMap = new HashMap<String, Integer>();
+            // 鑾峰彇琛ㄥご
+            Row heard = sheet.getRow(titleNum);
+            for (int i = 0; i < heard.getPhysicalNumberOfCells(); i++)
+            {
+                Cell cell = heard.getCell(i);
+                if (StringUtils.isNotNull(cell))
+                {
+                    String value = this.getCellValue(heard, i).toString();
+                    cellMap.put(value, i);
+                }
+                else
+                {
+                    cellMap.put(null, i);
+                }
+            }
+            // 鏈夋暟鎹椂鎵嶅鐞� 寰楀埌绫荤殑鎵�鏈塮ield.
+            List<Object[]> fields = this.getFields();
+            Map<Integer, Object[]> fieldsMap = new HashMap<Integer, Object[]>();
+            for (Object[] objects : fields)
+            {
+                Excel attr = (Excel) objects[1];
+                Integer column = cellMap.get(attr.name());
+                if (column != null)
+                {
+                    fieldsMap.put(column, objects);
+                }
+            }
+            for (int i = titleNum + 1; i <= rows; i++)
+            {
+                // 浠庣2琛屽紑濮嬪彇鏁版嵁,榛樿绗竴琛屾槸琛ㄥご.
+                Row row = sheet.getRow(i);
+                // 鍒ゆ柇褰撳墠琛屾槸鍚︽槸绌鸿
+                if (isRowEmpty(row))
+                {
+                    continue;
+                }
+                T entity = null;
+                for (Map.Entry<Integer, Object[]> entry : fieldsMap.entrySet())
+                {
+                    Object val = this.getCellValue(row, entry.getKey());
+
+                    // 濡傛灉涓嶅瓨鍦ㄥ疄渚嬪垯鏂板缓.
+                    entity = (entity == null ? clazz.newInstance() : entity);
+                    // 浠巑ap涓緱鍒板搴斿垪鐨刦ield.
+                    Field field = (Field) entry.getValue()[0];
+                    Excel attr = (Excel) entry.getValue()[1];
+                    // 鍙栧緱绫诲瀷,骞舵牴鎹璞$被鍨嬭缃��.
+                    Class<?> fieldType = field.getType();
+                    if (String.class == fieldType)
+                    {
+                        String s = Convert.toStr(val);
+                        if (StringUtils.endsWith(s, ".0"))
+                        {
+                            val = StringUtils.substringBefore(s, ".0");
+                        }
+                        else
+                        {
+                            String dateFormat = field.getAnnotation(Excel.class).dateFormat();
+                            if (StringUtils.isNotEmpty(dateFormat))
+                            {
+                                val = parseDateToStr(dateFormat, val);
+                            }
+                            else
+                            {
+                                val = Convert.toStr(val);
+                            }
+                        }
+                    }
+                    else if ((Integer.TYPE == fieldType || Integer.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val)))
+                    {
+                        val = Convert.toInt(val);
+                    }
+                    else if ((Long.TYPE == fieldType || Long.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val)))
+                    {
+                        val = Convert.toLong(val);
+                    }
+                    else if (Double.TYPE == fieldType || Double.class == fieldType)
+                    {
+                        val = Convert.toDouble(val);
+                    }
+                    else if (Float.TYPE == fieldType || Float.class == fieldType)
+                    {
+                        val = Convert.toFloat(val);
+                    }
+                    else if (BigDecimal.class == fieldType)
+                    {
+                        val = Convert.toBigDecimal(val);
+                    }
+                    else if (Date.class == fieldType)
+                    {
+                        if (val instanceof String)
+                        {
+                            val = DateUtils.parseDate(val);
+                        }
+                        else if (val instanceof Double)
+                        {
+                            val = DateUtil.getJavaDate((Double) val);
+                        }
+                    }
+                    else if (Boolean.TYPE == fieldType || Boolean.class == fieldType)
+                    {
+                        val = Convert.toBool(val, false);
+                    }
+                    if (StringUtils.isNotNull(fieldType))
+                    {
+                        String propertyName = field.getName();
+                        if (StringUtils.isNotEmpty(attr.targetAttr()))
+                        {
+                            propertyName = field.getName() + "." + attr.targetAttr();
+                        }
+                        if (StringUtils.isNotEmpty(attr.readConverterExp()))
+                        {
+                            val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator());
+                        }
+                        else if (StringUtils.isNotEmpty(attr.dictType()))
+                        {
+                            val = reverseDictByExp(Convert.toStr(val), attr.dictType(), attr.separator());
+                        }
+                        else if (!attr.handler().equals(ExcelHandlerAdapter.class))
+                        {
+                            val = dataFormatHandlerAdapter(val, attr, null);
+                        }
+                        else if (ColumnType.IMAGE == attr.cellType() && StringUtils.isNotEmpty(pictures))
+                        {
+                            PictureData image = pictures.get(row.getRowNum() + "_" + entry.getKey());
+                            if (image == null)
+                            {
+                                val = "";
+                            }
+                            else
+                            {
+                                byte[] data = image.getData();
+                                val = FileUtils.writeImportBytes(data);
+                            }
+                        }
+                        ReflectUtils.invokeSetter(entity, propertyName, val);
+                    }
+                }
+                list.add(entity);
+            }
+        }
+        return list;
+    }
+
+    /**
+     * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟
+     * 
+     * @param list 瀵煎嚭鏁版嵁闆嗗悎
+     * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
+     * @return 缁撴灉
+     */
+    public AjaxResult exportExcel(List<T> list, String sheetName)
+    {
+        return exportExcel(list, sheetName, StringUtils.EMPTY);
+    }
+
+    /**
+     * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟
+     * 
+     * @param list 瀵煎嚭鏁版嵁闆嗗悎
+     * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
+     * @param title 鏍囬
+     * @return 缁撴灉
+     */
+    public AjaxResult exportExcel(List<T> list, String sheetName, String title)
+    {
+        this.init(list, sheetName, title, Type.EXPORT);
+        return exportExcel();
+    }
+
+    /**
+     * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟
+     * 
+     * @param response 杩斿洖鏁版嵁
+     * @param list 瀵煎嚭鏁版嵁闆嗗悎
+     * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
+     * @return 缁撴灉
+     */
+    public void exportExcel(HttpServletResponse response, List<T> list, String sheetName)
+    {
+        exportExcel(response, list, sheetName, StringUtils.EMPTY);
+    }
+
+    /**
+     * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟
+     * 
+     * @param response 杩斿洖鏁版嵁
+     * @param list 瀵煎嚭鏁版嵁闆嗗悎
+     * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
+     * @param title 鏍囬
+     * @return 缁撴灉
+     */
+    public void exportExcel(HttpServletResponse response, List<T> list, String sheetName, String title)
+    {
+        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+        response.setCharacterEncoding("utf-8");
+        this.init(list, sheetName, title, Type.EXPORT);
+        exportExcel(response);
+    }
+
+    /**
+     * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟
+     * 
+     * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
+     * @return 缁撴灉
+     */
+    public AjaxResult importTemplateExcel(String sheetName)
+    {
+        return importTemplateExcel(sheetName, StringUtils.EMPTY);
+    }
+
+    /**
+     * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟
+     * 
+     * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
+     * @param title 鏍囬
+     * @return 缁撴灉
+     */
+    public AjaxResult importTemplateExcel(String sheetName, String title)
+    {
+        this.init(null, sheetName, title, Type.IMPORT);
+        return exportExcel();
+    }
+
+    /**
+     * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟
+     * 
+     * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
+     * @return 缁撴灉
+     */
+    public void importTemplateExcel(HttpServletResponse response, String sheetName)
+    {
+        importTemplateExcel(response, sheetName, StringUtils.EMPTY);
+    }
+
+    /**
+     * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟
+     * 
+     * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
+     * @param title 鏍囬
+     * @return 缁撴灉
+     */
+    public void importTemplateExcel(HttpServletResponse response, String sheetName, String title)
+    {
+        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+        response.setCharacterEncoding("utf-8");
+        this.init(null, sheetName, title, Type.IMPORT);
+        exportExcel(response);
+    }
+
+    /**
+     * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟
+     * 
+     * @return 缁撴灉
+     */
+    public void exportExcel(HttpServletResponse response)
+    {
+        try
+        {
+            writeSheet();
+            wb.write(response.getOutputStream());
+        }
+        catch (Exception e)
+        {
+            log.error("瀵煎嚭Excel寮傚父{}", e.getMessage());
+        }
+        finally
+        {
+            IOUtils.closeQuietly(wb);
+        }
+    }
+
+    /**
+     * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟
+     * 
+     * @return 缁撴灉
+     */
+    public AjaxResult exportExcel()
+    {
+        OutputStream out = null;
+        try
+        {
+            writeSheet();
+            String filename = encodingFilename(sheetName);
+            out = new FileOutputStream(getAbsoluteFile(filename));
+            wb.write(out);
+            return AjaxResult.success(filename);
+        }
+        catch (Exception e)
+        {
+            log.error("瀵煎嚭Excel寮傚父{}", e.getMessage());
+            throw new UtilException("瀵煎嚭Excel澶辫触锛岃鑱旂郴缃戠珯绠$悊鍛橈紒");
+        }
+        finally
+        {
+            IOUtils.closeQuietly(wb);
+            IOUtils.closeQuietly(out);
+        }
+    }
+
+    /**
+     * 鍒涘缓鍐欏叆鏁版嵁鍒癝heet
+     */
+    public void writeSheet()
+    {
+        // 鍙栧嚭涓�鍏辨湁澶氬皯涓猻heet.
+        int sheetNo = Math.max(1, (int) Math.ceil(list.size() * 1.0 / sheetSize));
+        for (int index = 0; index < sheetNo; index++)
+        {
+            createSheet(sheetNo, index);
+
+            // 浜х敓涓�琛�
+            Row row = sheet.createRow(rownum);
+            int column = 0;
+            // 鍐欏叆鍚勪釜瀛楁鐨勫垪澶村悕绉�
+            for (Object[] os : fields)
+            {
+                Field field = (Field) os[0];
+                Excel excel = (Excel) os[1];
+                if (Collection.class.isAssignableFrom(field.getType()))
+                {
+                    for (Field subField : subFields)
+                    {
+                        Excel subExcel = subField.getAnnotation(Excel.class);
+                        this.createHeadCell(subExcel, row, column++);
+                    }
+                }
+                else
+                {
+                    this.createHeadCell(excel, row, column++);
+                }
+            }
+            if (Type.EXPORT.equals(type))
+            {
+                fillExcelData(index, row);
+                addStatisticsRow();
+            }
+        }
+    }
+
+    /**
+     * 濉厖excel鏁版嵁
+     * 
+     * @param index 搴忓彿
+     * @param row 鍗曞厓鏍艰
+     */
+    @SuppressWarnings("unchecked")
+    public void fillExcelData(int index, Row row)
+    {
+        int startNo = index * sheetSize;
+        int endNo = Math.min(startNo + sheetSize, list.size());
+        int rowNo = (1 + rownum) - startNo;
+        for (int i = startNo; i < endNo; i++)
+        {
+            rowNo = isSubList() ? (i > 1 ? rowNo + 1 : rowNo + i) : i + 1 + rownum - startNo;
+            row = sheet.createRow(rowNo);
+            // 寰楀埌瀵煎嚭瀵硅薄.
+            T vo = (T) list.get(i);
+            Collection<?> subList = null;
+            if (isSubList())
+            {
+                if (isSubListValue(vo))
+                {
+                    subList = getListCellValue(vo);
+                    subMergedLastRowNum = subMergedLastRowNum + subList.size();
+                }
+                else
+                {
+                    subMergedFirstRowNum++;
+                    subMergedLastRowNum++;
+                }
+            }
+            int column = 0;
+            for (Object[] os : fields)
+            {
+                Field field = (Field) os[0];
+                Excel excel = (Excel) os[1];
+                if (Collection.class.isAssignableFrom(field.getType()) && StringUtils.isNotNull(subList))
+                {
+                    boolean subFirst = false;
+                    for (Object obj : subList)
+                    {
+                        if (subFirst)
+                        {
+                            rowNo++;
+                            row = sheet.createRow(rowNo);
+                        }
+                        List<Field> subFields = FieldUtils.getFieldsListWithAnnotation(obj.getClass(), Excel.class);
+                        int subIndex = 0;
+                        for (Field subField : subFields)
+                        {
+                            if (subField.isAnnotationPresent(Excel.class))
+                            {
+                                subField.setAccessible(true);
+                                Excel attr = subField.getAnnotation(Excel.class);
+                                this.addCell(attr, row, (T) obj, subField, column + subIndex);
+                            }
+                            subIndex++;
+                        }
+                        subFirst = true;
+                    }
+                    this.subMergedFirstRowNum = this.subMergedFirstRowNum + subList.size();
+                }
+                else
+                {
+                    this.addCell(excel, row, vo, field, column++);
+                }
+            }
+        }
+    }
+
+    /**
+     * 鍒涘缓琛ㄦ牸鏍峰紡
+     * 
+     * @param wb 宸ヤ綔钖勫璞�
+     * @return 鏍峰紡鍒楄〃
+     */
+    private Map<String, CellStyle> createStyles(Workbook wb)
+    {
+        // 鍐欏叆鍚勬潯璁板綍,姣忔潯璁板綍瀵瑰簲excel琛ㄤ腑鐨勪竴琛�
+        Map<String, CellStyle> styles = new HashMap<String, CellStyle>();
+        CellStyle style = wb.createCellStyle();
+        style.setAlignment(HorizontalAlignment.CENTER);
+        style.setVerticalAlignment(VerticalAlignment.CENTER);
+        Font titleFont = wb.createFont();
+        titleFont.setFontName("Arial");
+        titleFont.setFontHeightInPoints((short) 16);
+        titleFont.setBold(true);
+        style.setFont(titleFont);
+        styles.put("title", style);
+
+        style = wb.createCellStyle();
+        style.setAlignment(HorizontalAlignment.CENTER);
+        style.setVerticalAlignment(VerticalAlignment.CENTER);
+        style.setBorderRight(BorderStyle.THIN);
+        style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+        style.setBorderLeft(BorderStyle.THIN);
+        style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+        style.setBorderTop(BorderStyle.THIN);
+        style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+        style.setBorderBottom(BorderStyle.THIN);
+        style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+        Font dataFont = wb.createFont();
+        dataFont.setFontName("Arial");
+        dataFont.setFontHeightInPoints((short) 10);
+        style.setFont(dataFont);
+        styles.put("data", style);
+
+        style = wb.createCellStyle();
+        style.setAlignment(HorizontalAlignment.CENTER);
+        style.setVerticalAlignment(VerticalAlignment.CENTER);
+        Font totalFont = wb.createFont();
+        totalFont.setFontName("Arial");
+        totalFont.setFontHeightInPoints((short) 10);
+        style.setFont(totalFont);
+        styles.put("total", style);
+
+        styles.putAll(annotationHeaderStyles(wb, styles));
+
+        styles.putAll(annotationDataStyles(wb));
+
+        return styles;
+    }
+
+    /**
+     * 鏍规嵁Excel娉ㄨВ鍒涘缓琛ㄦ牸澶存牱寮�
+     * 
+     * @param wb 宸ヤ綔钖勫璞�
+     * @return 鑷畾涔夋牱寮忓垪琛�
+     */
+    private Map<String, CellStyle> annotationHeaderStyles(Workbook wb, Map<String, CellStyle> styles)
+    {
+        Map<String, CellStyle> headerStyles = new HashMap<String, CellStyle>();
+        for (Object[] os : fields)
+        {
+            Excel excel = (Excel) os[1];
+            String key = StringUtils.format("header_{}_{}", excel.headerColor(), excel.headerBackgroundColor());
+            if (!headerStyles.containsKey(key))
+            {
+                CellStyle style = wb.createCellStyle();
+                style.cloneStyleFrom(styles.get("data"));
+                style.setAlignment(HorizontalAlignment.CENTER);
+                style.setVerticalAlignment(VerticalAlignment.CENTER);
+                style.setFillForegroundColor(excel.headerBackgroundColor().index);
+                style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+                Font headerFont = wb.createFont();
+                headerFont.setFontName("Arial");
+                headerFont.setFontHeightInPoints((short) 10);
+                headerFont.setBold(true);
+                headerFont.setColor(excel.headerColor().index);
+                style.setFont(headerFont);
+                headerStyles.put(key, style);
+            }
+        }
+        return headerStyles;
+    }
+
+    /**
+     * 鏍规嵁Excel娉ㄨВ鍒涘缓琛ㄦ牸鍒楁牱寮�
+     * 
+     * @param wb 宸ヤ綔钖勫璞�
+     * @return 鑷畾涔夋牱寮忓垪琛�
+     */
+    private Map<String, CellStyle> annotationDataStyles(Workbook wb)
+    {
+        Map<String, CellStyle> styles = new HashMap<String, CellStyle>();
+        for (Object[] os : fields)
+        {
+            Excel excel = (Excel) os[1];
+            String key = StringUtils.format("data_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor());
+            if (!styles.containsKey(key))
+            {
+                CellStyle style = wb.createCellStyle();
+                style.setAlignment(excel.align());
+                style.setVerticalAlignment(VerticalAlignment.CENTER);
+                style.setBorderRight(BorderStyle.THIN);
+                style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+                style.setBorderLeft(BorderStyle.THIN);
+                style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+                style.setBorderTop(BorderStyle.THIN);
+                style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+                style.setBorderBottom(BorderStyle.THIN);
+                style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+                style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+                style.setFillForegroundColor(excel.backgroundColor().getIndex());
+                Font dataFont = wb.createFont();
+                dataFont.setFontName("Arial");
+                dataFont.setFontHeightInPoints((short) 10);
+                dataFont.setColor(excel.color().index);
+                style.setFont(dataFont);
+                styles.put(key, style);
+            }
+        }
+        return styles;
+    }
+
+    /**
+     * 鍒涘缓鍗曞厓鏍�
+     */
+    public Cell createHeadCell(Excel attr, Row row, int column)
+    {
+        // 鍒涘缓鍒�
+        Cell cell = row.createCell(column);
+        // 鍐欏叆鍒椾俊鎭�
+        cell.setCellValue(attr.name());
+        setDataValidation(attr, row, column);
+        cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));
+        if (isSubList())
+        {
+            // 濉厖榛樿鏍峰紡锛岄槻姝㈠悎骞跺崟鍏冩牸鏍峰紡澶辨晥
+            sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor())));
+            if (attr.needMerge())
+            {
+                sheet.addMergedRegion(new CellRangeAddress(rownum - 1, rownum, column, column));
+            }
+        }
+        return cell;
+    }
+
+    /**
+     * 璁剧疆鍗曞厓鏍间俊鎭�
+     * 
+     * @param value 鍗曞厓鏍煎��
+     * @param attr 娉ㄨВ鐩稿叧
+     * @param cell 鍗曞厓鏍间俊鎭�
+     */
+    public void setCellVo(Object value, Excel attr, Cell cell)
+    {
+        if (ColumnType.STRING == attr.cellType())
+        {
+            String cellValue = Convert.toStr(value);
+            // 瀵逛簬浠讳綍浠ヨ〃杈惧紡瑙﹀彂瀛楃 =-+@寮�澶寸殑鍗曞厓鏍硷紝鐩存帴浣跨敤tab瀛楃浣滀负鍓嶇紑锛岄槻姝SV娉ㄥ叆銆�
+            if (StringUtils.startsWithAny(cellValue, FORMULA_STR))
+            {
+                cellValue = RegExUtils.replaceFirst(cellValue, FORMULA_REGEX_STR, "\t$0");
+            }
+            if (value instanceof Collection && StringUtils.equals("[]", cellValue))
+            {
+                cellValue = StringUtils.EMPTY;
+            }
+            cell.setCellValue(StringUtils.isNull(cellValue) ? attr.defaultValue() : cellValue + attr.suffix());
+        }
+        else if (ColumnType.NUMERIC == attr.cellType())
+        {
+            if (StringUtils.isNotNull(value))
+            {
+                cell.setCellValue(StringUtils.contains(Convert.toStr(value), ".") ? Convert.toDouble(value) : Convert.toInt(value));
+            }
+        }
+        else if (ColumnType.IMAGE == attr.cellType())
+        {
+            ClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + 1), cell.getRow().getRowNum() + 1);
+            String imagePath = Convert.toStr(value);
+            if (StringUtils.isNotEmpty(imagePath))
+            {
+                byte[] data = ImageUtils.getImage(imagePath);
+                getDrawingPatriarch(cell.getSheet()).createPicture(anchor,
+                        cell.getSheet().getWorkbook().addPicture(data, getImageType(data)));
+            }
+        }
+    }
+
+    /**
+     * 鑾峰彇鐢诲竷
+     */
+    public static Drawing<?> getDrawingPatriarch(Sheet sheet)
+    {
+        if (sheet.getDrawingPatriarch() == null)
+        {
+            sheet.createDrawingPatriarch();
+        }
+        return sheet.getDrawingPatriarch();
+    }
+
+    /**
+     * 鑾峰彇鍥剧墖绫诲瀷,璁剧疆鍥剧墖鎻掑叆绫诲瀷
+     */
+    public int getImageType(byte[] value)
+    {
+        String type = FileTypeUtils.getFileExtendName(value);
+        if ("JPG".equalsIgnoreCase(type))
+        {
+            return Workbook.PICTURE_TYPE_JPEG;
+        }
+        else if ("PNG".equalsIgnoreCase(type))
+        {
+            return Workbook.PICTURE_TYPE_PNG;
+        }
+        return Workbook.PICTURE_TYPE_JPEG;
+    }
+
+    /**
+     * 鍒涘缓琛ㄦ牸鏍峰紡
+     */
+    public void setDataValidation(Excel attr, Row row, int column)
+    {
+        if (attr.name().indexOf("娉細") >= 0)
+        {
+            sheet.setColumnWidth(column, 6000);
+        }
+        else
+        {
+            // 璁剧疆鍒楀
+            sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256));
+        }
+        if (StringUtils.isNotEmpty(attr.prompt()) || attr.combo().length > 0)
+        {
+            if (attr.combo().length > 15 || StringUtils.join(attr.combo()).length() > 255)
+            {
+                // 濡傛灉涓嬫媺鏁板ぇ浜�15鎴栧瓧绗︿覆闀垮害澶т簬255锛屽垯浣跨敤涓�涓柊sheet瀛樺偍锛岄伩鍏嶇敓鎴愮殑妯℃澘涓嬫媺鍊艰幏鍙栦笉鍒�
+                setXSSFValidationWithHidden(sheet, attr.combo(), attr.prompt(), 1, 100, column, column);
+            }
+            else
+            {
+                // 鎻愮ず淇℃伅鎴栧彧鑳介�夋嫨涓嶈兘杈撳叆鐨勫垪鍐呭.
+                setPromptOrValidation(sheet, attr.combo(), attr.prompt(), 1, 100, column, column);
+            }
+        }
+    }
+
+    /**
+     * 娣诲姞鍗曞厓鏍�
+     */
+    public Cell addCell(Excel attr, Row row, T vo, Field field, int column)
+    {
+        Cell cell = null;
+        try
+        {
+            // 璁剧疆琛岄珮
+            row.setHeight(maxHeight);
+            // 鏍规嵁Excel涓缃儏鍐靛喅瀹氭槸鍚﹀鍑�,鏈変簺鎯呭喌闇�瑕佷繚鎸佷负绌�,甯屾湜鐢ㄦ埛濉啓杩欎竴鍒�.
+            if (attr.isExport())
+            {
+                // 鍒涘缓cell
+                cell = row.createCell(column);
+                if (isSubListValue(vo) && getListCellValue(vo).size() > 1 && attr.needMerge())
+                {
+                    CellRangeAddress cellAddress = new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column);
+                    sheet.addMergedRegion(cellAddress);
+                }
+                cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor())));
+
+                // 鐢ㄤ簬璇诲彇瀵硅薄涓殑灞炴��
+                Object value = getTargetValue(vo, field, attr);
+                String dateFormat = attr.dateFormat();
+                String readConverterExp = attr.readConverterExp();
+                String separator = attr.separator();
+                String dictType = attr.dictType();
+                if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value))
+                {
+                    cell.setCellValue(parseDateToStr(dateFormat, value));
+                }
+                else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value))
+                {
+                    cell.setCellValue(convertByExp(Convert.toStr(value), readConverterExp, separator));
+                }
+                else if (StringUtils.isNotEmpty(dictType) && StringUtils.isNotNull(value))
+                {
+                    if (!sysDictMap.containsKey(dictType + value))
+                    {
+                        String lable = convertDictByExp(Convert.toStr(value), dictType, separator);
+                        sysDictMap.put(dictType + value, lable);
+                    }
+                    cell.setCellValue(sysDictMap.get(dictType + value));
+                }
+                else if (value instanceof BigDecimal && -1 != attr.scale())
+                {
+                    cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).doubleValue());
+                }
+                else if (!attr.handler().equals(ExcelHandlerAdapter.class))
+                {
+                    cell.setCellValue(dataFormatHandlerAdapter(value, attr, cell));
+                }
+                else
+                {
+                    // 璁剧疆鍒楃被鍨�
+                    setCellVo(value, attr, cell);
+                }
+                addStatisticsData(column, Convert.toStr(value), attr);
+            }
+        }
+        catch (Exception e)
+        {
+            log.error("瀵煎嚭Excel澶辫触{}", e);
+        }
+        return cell;
+    }
+
+    /**
+     * 璁剧疆 POI XSSFSheet 鍗曞厓鏍兼彁绀烘垨閫夋嫨妗�
+     * 
+     * @param sheet 琛ㄥ崟
+     * @param textlist 涓嬫媺妗嗘樉绀虹殑鍐呭
+     * @param promptContent 鎻愮ず鍐呭
+     * @param firstRow 寮�濮嬭
+     * @param endRow 缁撴潫琛�
+     * @param firstCol 寮�濮嬪垪
+     * @param endCol 缁撴潫鍒�
+     */
+    public void setPromptOrValidation(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow,
+            int firstCol, int endCol)
+    {
+        DataValidationHelper helper = sheet.getDataValidationHelper();
+        DataValidationConstraint constraint = textlist.length > 0 ? helper.createExplicitListConstraint(textlist) : helper.createCustomConstraint("DD1");
+        CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
+        DataValidation dataValidation = helper.createValidation(constraint, regions);
+        if (StringUtils.isNotEmpty(promptContent))
+        {
+            // 濡傛灉璁剧疆浜嗘彁绀轰俊鎭垯榧犳爣鏀句笂鍘绘彁绀�
+            dataValidation.createPromptBox("", promptContent);
+            dataValidation.setShowPromptBox(true);
+        }
+        // 澶勭悊Excel鍏煎鎬ч棶棰�
+        if (dataValidation instanceof XSSFDataValidation)
+        {
+            dataValidation.setSuppressDropDownArrow(true);
+            dataValidation.setShowErrorBox(true);
+        }
+        else
+        {
+            dataValidation.setSuppressDropDownArrow(false);
+        }
+        sheet.addValidationData(dataValidation);
+    }
+
+    /**
+     * 璁剧疆鏌愪簺鍒楃殑鍊煎彧鑳借緭鍏ラ鍒剁殑鏁版嵁,鏄剧ず涓嬫媺妗嗭紙鍏煎瓒呭嚭涓�瀹氭暟閲忕殑涓嬫媺妗嗭級.
+     * 
+     * @param sheet 瑕佽缃殑sheet.
+     * @param textlist 涓嬫媺妗嗘樉绀虹殑鍐呭
+     * @param promptContent 鎻愮ず鍐呭
+     * @param firstRow 寮�濮嬭
+     * @param endRow 缁撴潫琛�
+     * @param firstCol 寮�濮嬪垪
+     * @param endCol 缁撴潫鍒�
+     */
+    public void setXSSFValidationWithHidden(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow, int firstCol, int endCol)
+    {
+        String hideSheetName = "combo_" + firstCol + "_" + endCol;
+        Sheet hideSheet = wb.createSheet(hideSheetName); // 鐢ㄤ簬瀛樺偍 涓嬫媺鑿滃崟鏁版嵁
+        for (int i = 0; i < textlist.length; i++)
+        {
+            hideSheet.createRow(i).createCell(0).setCellValue(textlist[i]);
+        }
+        // 鍒涘缓鍚嶇О锛屽彲琚叾浠栧崟鍏冩牸寮曠敤
+        Name name = wb.createName();
+        name.setNameName(hideSheetName + "_data");
+        name.setRefersToFormula(hideSheetName + "!$A$1:$A$" + textlist.length);
+        DataValidationHelper helper = sheet.getDataValidationHelper();
+        // 鍔犺浇涓嬫媺鍒楄〃鍐呭
+        DataValidationConstraint constraint = helper.createFormulaListConstraint(hideSheetName + "_data");
+        // 璁剧疆鏁版嵁鏈夋晥鎬у姞杞藉湪鍝釜鍗曞厓鏍间笂,鍥涗釜鍙傛暟鍒嗗埆鏄細璧峰琛屻�佺粓姝㈣銆佽捣濮嬪垪銆佺粓姝㈠垪
+        CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
+        // 鏁版嵁鏈夋晥鎬у璞�
+        DataValidation dataValidation = helper.createValidation(constraint, regions);
+        if (StringUtils.isNotEmpty(promptContent))
+        {
+            // 濡傛灉璁剧疆浜嗘彁绀轰俊鎭垯榧犳爣鏀句笂鍘绘彁绀�
+            dataValidation.createPromptBox("", promptContent);
+            dataValidation.setShowPromptBox(true);
+        }
+        // 澶勭悊Excel鍏煎鎬ч棶棰�
+        if (dataValidation instanceof XSSFDataValidation)
+        {
+            dataValidation.setSuppressDropDownArrow(true);
+            dataValidation.setShowErrorBox(true);
+        }
+        else
+        {
+            dataValidation.setSuppressDropDownArrow(false);
+        }
+
+        sheet.addValidationData(dataValidation);
+        // 璁剧疆hiddenSheet闅愯棌
+        wb.setSheetHidden(wb.getSheetIndex(hideSheet), true);
+    }
+
+    /**
+     * 瑙f瀽瀵煎嚭鍊� 0=鐢�,1=濂�,2=鏈煡
+     * 
+     * @param propertyValue 鍙傛暟鍊�
+     * @param converterExp 缈昏瘧娉ㄨВ
+     * @param separator 鍒嗛殧绗�
+     * @return 瑙f瀽鍚庡��
+     */
+    public static String convertByExp(String propertyValue, String converterExp, String separator)
+    {
+        StringBuilder propertyString = new StringBuilder();
+        String[] convertSource = converterExp.split(",");
+        for (String item : convertSource)
+        {
+            String[] itemArray = item.split("=");
+            if (StringUtils.containsAny(propertyValue, separator))
+            {
+                for (String value : propertyValue.split(separator))
+                {
+                    if (itemArray[0].equals(value))
+                    {
+                        propertyString.append(itemArray[1] + separator);
+                        break;
+                    }
+                }
+            }
+            else
+            {
+                if (itemArray[0].equals(propertyValue))
+                {
+                    return itemArray[1];
+                }
+            }
+        }
+        return StringUtils.stripEnd(propertyString.toString(), separator);
+    }
+
+    /**
+     * 鍙嶅悜瑙f瀽鍊� 鐢�=0,濂�=1,鏈煡=2
+     * 
+     * @param propertyValue 鍙傛暟鍊�
+     * @param converterExp 缈昏瘧娉ㄨВ
+     * @param separator 鍒嗛殧绗�
+     * @return 瑙f瀽鍚庡��
+     */
+    public static String reverseByExp(String propertyValue, String converterExp, String separator)
+    {
+        StringBuilder propertyString = new StringBuilder();
+        String[] convertSource = converterExp.split(",");
+        for (String item : convertSource)
+        {
+            String[] itemArray = item.split("=");
+            if (StringUtils.containsAny(propertyValue, separator))
+            {
+                for (String value : propertyValue.split(separator))
+                {
+                    if (itemArray[1].equals(value))
+                    {
+                        propertyString.append(itemArray[0] + separator);
+                        break;
+                    }
+                }
+            }
+            else
+            {
+                if (itemArray[1].equals(propertyValue))
+                {
+                    return itemArray[0];
+                }
+            }
+        }
+        return StringUtils.stripEnd(propertyString.toString(), separator);
+    }
+
+    /**
+     * 瑙f瀽瀛楀吀鍊�
+     * 
+     * @param dictValue 瀛楀吀鍊�
+     * @param dictType 瀛楀吀绫诲瀷
+     * @param separator 鍒嗛殧绗�
+     * @return 瀛楀吀鏍囩
+     */
+    public static String convertDictByExp(String dictValue, String dictType, String separator)
+    {
+        return DictUtils.getDictLabel(dictType, dictValue, separator);
+    }
+
+    /**
+     * 鍙嶅悜瑙f瀽鍊煎瓧鍏稿��
+     * 
+     * @param dictLabel 瀛楀吀鏍囩
+     * @param dictType 瀛楀吀绫诲瀷
+     * @param separator 鍒嗛殧绗�
+     * @return 瀛楀吀鍊�
+     */
+    public static String reverseDictByExp(String dictLabel, String dictType, String separator)
+    {
+        return DictUtils.getDictValue(dictType, dictLabel, separator);
+    }
+
+    /**
+     * 鏁版嵁澶勭悊鍣�
+     * 
+     * @param value 鏁版嵁鍊�
+     * @param excel 鏁版嵁娉ㄨВ
+     * @return
+     */
+    public String dataFormatHandlerAdapter(Object value, Excel excel, Cell cell)
+    {
+        try
+        {
+            Object instance = excel.handler().newInstance();
+            Method formatMethod = excel.handler().getMethod("format", new Class[] { Object.class, String[].class, Cell.class, Workbook.class });
+            value = formatMethod.invoke(instance, value, excel.args(), cell, this.wb);
+        }
+        catch (Exception e)
+        {
+            log.error("涓嶈兘鏍煎紡鍖栨暟鎹� " + excel.handler(), e.getMessage());
+        }
+        return Convert.toStr(value);
+    }
+
+    /**
+     * 鍚堣缁熻淇℃伅
+     */
+    private void addStatisticsData(Integer index, String text, Excel entity)
+    {
+        if (entity != null && entity.isStatistics())
+        {
+            Double temp = 0D;
+            if (!statistics.containsKey(index))
+            {
+                statistics.put(index, temp);
+            }
+            try
+            {
+                temp = Double.valueOf(text);
+            }
+            catch (NumberFormatException e)
+            {
+            }
+            statistics.put(index, statistics.get(index) + temp);
+        }
+    }
+
+    /**
+     * 鍒涘缓缁熻琛�
+     */
+    public void addStatisticsRow()
+    {
+        if (statistics.size() > 0)
+        {
+            Row row = sheet.createRow(sheet.getLastRowNum() + 1);
+            Set<Integer> keys = statistics.keySet();
+            Cell cell = row.createCell(0);
+            cell.setCellStyle(styles.get("total"));
+            cell.setCellValue("鍚堣");
+
+            for (Integer key : keys)
+            {
+                cell = row.createCell(key);
+                cell.setCellStyle(styles.get("total"));
+                cell.setCellValue(DOUBLE_FORMAT.format(statistics.get(key)));
+            }
+            statistics.clear();
+        }
+    }
+
+    /**
+     * 缂栫爜鏂囦欢鍚�
+     */
+    public String encodingFilename(String filename)
+    {
+        filename = UUID.randomUUID() + "_" + filename + ".xlsx";
+        return filename;
+    }
+
+    /**
+     * 鑾峰彇涓嬭浇璺緞
+     * 
+     * @param filename 鏂囦欢鍚嶇О
+     */
+    public String getAbsoluteFile(String filename)
+    {
+        String downloadPath = MesConfig.getDownloadPath() + filename;
+        File desc = new File(downloadPath);
+        if (!desc.getParentFile().exists())
+        {
+            desc.getParentFile().mkdirs();
+        }
+        return downloadPath;
+    }
+
+    /**
+     * 鑾峰彇bean涓殑灞炴�у��
+     * 
+     * @param vo 瀹炰綋瀵硅薄
+     * @param field 瀛楁
+     * @param excel 娉ㄨВ
+     * @return 鏈�缁堢殑灞炴�у��
+     * @throws Exception
+     */
+    private Object getTargetValue(T vo, Field field, Excel excel) throws Exception
+    {
+        Object o = field.get(vo);
+        if (StringUtils.isNotEmpty(excel.targetAttr()))
+        {
+            String target = excel.targetAttr();
+            if (target.contains("."))
+            {
+                String[] targets = target.split("[.]");
+                for (String name : targets)
+                {
+                    o = getValue(o, name);
+                }
+            }
+            else
+            {
+                o = getValue(o, target);
+            }
+        }
+        return o;
+    }
+
+    /**
+     * 浠ョ被鐨勫睘鎬х殑get鏂规硶鏂规硶褰㈠紡鑾峰彇鍊�
+     * 
+     * @param o
+     * @param name
+     * @return value
+     * @throws Exception
+     */
+    private Object getValue(Object o, String name) throws Exception
+    {
+        if (StringUtils.isNotNull(o) && StringUtils.isNotEmpty(name))
+        {
+            Class<?> clazz = o.getClass();
+            Field field = clazz.getDeclaredField(name);
+            field.setAccessible(true);
+            o = field.get(o);
+        }
+        return o;
+    }
+
+    /**
+     * 寰楀埌鎵�鏈夊畾涔夊瓧娈�
+     */
+    private void createExcelField()
+    {
+        this.fields = getFields();
+        this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList());
+        this.maxHeight = getRowHeight();
+    }
+
+    /**
+     * 鑾峰彇瀛楁娉ㄨВ淇℃伅
+     */
+    public List<Object[]> getFields()
+    {
+        List<Object[]> fields = new ArrayList<Object[]>();
+        List<Field> tempFields = new ArrayList<>();
+        tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));
+        tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
+        for (Field field : tempFields)
+        {
+            if (!ArrayUtils.contains(this.excludeFields, field.getName()))
+            {
+                // 鍗曟敞瑙�
+                if (field.isAnnotationPresent(Excel.class))
+                {
+                    Excel attr = field.getAnnotation(Excel.class);
+                    if (attr != null && (attr.type() == Type.ALL || attr.type() == type))
+                    {
+                        field.setAccessible(true);
+                        fields.add(new Object[] { field, attr });
+                    }
+                    if (Collection.class.isAssignableFrom(field.getType()))
+                    {
+                        subMethod = getSubMethod(field.getName(), clazz);
+                        ParameterizedType pt = (ParameterizedType) field.getGenericType();
+                        Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0];
+                        this.subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class);
+                    }
+                }
+
+                // 澶氭敞瑙�
+                if (field.isAnnotationPresent(Excels.class))
+                {
+                    Excels attrs = field.getAnnotation(Excels.class);
+                    Excel[] excels = attrs.value();
+                    for (Excel attr : excels)
+                    {
+                        if (!ArrayUtils.contains(this.excludeFields, field.getName() + "." + attr.targetAttr())
+                                && (attr != null && (attr.type() == Type.ALL || attr.type() == type)))
+                        {
+                            field.setAccessible(true);
+                            fields.add(new Object[] { field, attr });
+                        }
+                    }
+                }
+            }
+        }
+        return fields;
+    }
+
+    /**
+     * 鏍规嵁娉ㄨВ鑾峰彇鏈�澶ц楂�
+     */
+    public short getRowHeight()
+    {
+        double maxHeight = 0;
+        for (Object[] os : this.fields)
+        {
+            Excel excel = (Excel) os[1];
+            maxHeight = Math.max(maxHeight, excel.height());
+        }
+        return (short) (maxHeight * 20);
+    }
+
+    /**
+     * 鍒涘缓涓�涓伐浣滅翱
+     */
+    public void createWorkbook()
+    {
+        this.wb = new SXSSFWorkbook(500);
+        this.sheet = wb.createSheet();
+        wb.setSheetName(0, sheetName);
+        this.styles = createStyles(wb);
+    }
+
+    /**
+     * 鍒涘缓宸ヤ綔琛�
+     * 
+     * @param sheetNo sheet鏁伴噺
+     * @param index 搴忓彿
+     */
+    public void createSheet(int sheetNo, int index)
+    {
+        // 璁剧疆宸ヤ綔琛ㄧ殑鍚嶇О.
+        if (sheetNo > 1 && index > 0)
+        {
+            this.sheet = wb.createSheet();
+            this.createTitle();
+            wb.setSheetName(index, sheetName + index);
+        }
+    }
+
+    /**
+     * 鑾峰彇鍗曞厓鏍煎��
+     * 
+     * @param row 鑾峰彇鐨勮
+     * @param column 鑾峰彇鍗曞厓鏍煎垪鍙�
+     * @return 鍗曞厓鏍煎��
+     */
+    public Object getCellValue(Row row, int column)
+    {
+        if (row == null)
+        {
+            return row;
+        }
+        Object val = "";
+        try
+        {
+            Cell cell = row.getCell(column);
+            if (StringUtils.isNotNull(cell))
+            {
+                if (cell.getCellType() == CellType.NUMERIC || cell.getCellType() == CellType.FORMULA)
+                {
+                    val = cell.getNumericCellValue();
+                    if (DateUtil.isCellDateFormatted(cell))
+                    {
+                        val = DateUtil.getJavaDate((Double) val); // POI Excel 鏃ユ湡鏍煎紡杞崲
+                    }
+                    else
+                    {
+                        if ((Double) val % 1 != 0)
+                        {
+                            val = new BigDecimal(val.toString());
+                        }
+                        else
+                        {
+                            val = new DecimalFormat("0").format(val);
+                        }
+                    }
+                }
+                else if (cell.getCellType() == CellType.STRING)
+                {
+                    val = cell.getStringCellValue();
+                }
+                else if (cell.getCellType() == CellType.BOOLEAN)
+                {
+                    val = cell.getBooleanCellValue();
+                }
+                else if (cell.getCellType() == CellType.ERROR)
+                {
+                    val = cell.getErrorCellValue();
+                }
+
+            }
+        }
+        catch (Exception e)
+        {
+            return val;
+        }
+        return val;
+    }
+
+    /**
+     * 鍒ゆ柇鏄惁鏄┖琛�
+     * 
+     * @param row 鍒ゆ柇鐨勮
+     * @return
+     */
+    private boolean isRowEmpty(Row row)
+    {
+        if (row == null)
+        {
+            return true;
+        }
+        for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++)
+        {
+            Cell cell = row.getCell(i);
+            if (cell != null && cell.getCellType() != CellType.BLANK)
+            {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * 鑾峰彇Excel2003鍥剧墖
+     *
+     * @param sheet 褰撳墠sheet瀵硅薄
+     * @param workbook 宸ヤ綔绨垮璞�
+     * @return Map key:鍥剧墖鍗曞厓鏍肩储寮曪紙1_1锛塖tring锛寁alue:鍥剧墖娴丳ictureData
+     */
+    public static Map<String, PictureData> getSheetPictures03(HSSFSheet sheet, HSSFWorkbook workbook)
+    {
+        Map<String, PictureData> sheetIndexPicMap = new HashMap<String, PictureData>();
+        List<HSSFPictureData> pictures = workbook.getAllPictures();
+        if (!pictures.isEmpty())
+        {
+            for (HSSFShape shape : sheet.getDrawingPatriarch().getChildren())
+            {
+                HSSFClientAnchor anchor = (HSSFClientAnchor) shape.getAnchor();
+                if (shape instanceof HSSFPicture)
+                {
+                    HSSFPicture pic = (HSSFPicture) shape;
+                    int pictureIndex = pic.getPictureIndex() - 1;
+                    HSSFPictureData picData = pictures.get(pictureIndex);
+                    String picIndex = anchor.getRow1() + "_" + anchor.getCol1();
+                    sheetIndexPicMap.put(picIndex, picData);
+                }
+            }
+            return sheetIndexPicMap;
+        }
+        else
+        {
+            return sheetIndexPicMap;
+        }
+    }
+
+    /**
+     * 鑾峰彇Excel2007鍥剧墖
+     *
+     * @param sheet 褰撳墠sheet瀵硅薄
+     * @param workbook 宸ヤ綔绨垮璞�
+     * @return Map key:鍥剧墖鍗曞厓鏍肩储寮曪紙1_1锛塖tring锛寁alue:鍥剧墖娴丳ictureData
+     */
+    public static Map<String, PictureData> getSheetPictures07(XSSFSheet sheet, XSSFWorkbook workbook)
+    {
+        Map<String, PictureData> sheetIndexPicMap = new HashMap<String, PictureData>();
+        for (POIXMLDocumentPart dr : sheet.getRelations())
+        {
+            if (dr instanceof XSSFDrawing)
+            {
+                XSSFDrawing drawing = (XSSFDrawing) dr;
+                List<XSSFShape> shapes = drawing.getShapes();
+                for (XSSFShape shape : shapes)
+                {
+                    if (shape instanceof XSSFPicture)
+                    {
+                        XSSFPicture pic = (XSSFPicture) shape;
+                        XSSFClientAnchor anchor = pic.getPreferredSize();
+                        CTMarker ctMarker = anchor.getFrom();
+                        String picIndex = ctMarker.getRow() + "_" + ctMarker.getCol();
+                        sheetIndexPicMap.put(picIndex, pic.getPictureData());
+                    }
+                }
+            }
+        }
+        return sheetIndexPicMap;
+    }
+
+    /**
+     * 鏍煎紡鍖栦笉鍚岀被鍨嬬殑鏃ユ湡瀵硅薄
+     * 
+     * @param dateFormat 鏃ユ湡鏍煎紡
+     * @param val 琚牸寮忓寲鐨勬棩鏈熷璞�
+     * @return 鏍煎紡鍖栧悗鐨勬棩鏈熷瓧绗�
+     */
+    public String parseDateToStr(String dateFormat, Object val)
+    {
+        if (val == null)
+        {
+            return "";
+        }
+        String str;
+        if (val instanceof Date)
+        {
+            str = DateUtils.parseDateToStr(dateFormat, (Date) val);
+        }
+        else if (val instanceof LocalDateTime)
+        {
+            str = DateUtils.parseDateToStr(dateFormat, DateUtils.toDate((LocalDateTime) val));
+        }
+        else if (val instanceof LocalDate)
+        {
+            str = DateUtils.parseDateToStr(dateFormat, DateUtils.toDate((LocalDate) val));
+        }
+        else
+        {
+            str = val.toString();
+        }
+        return str;
+    }
+
+    /**
+     * 鏄惁鏈夊璞$殑瀛愬垪琛�
+     */
+    public boolean isSubList()
+    {
+        return StringUtils.isNotNull(subFields) && subFields.size() > 0;
+    }
+
+    /**
+     * 鏄惁鏈夊璞$殑瀛愬垪琛紝闆嗗悎涓嶄负绌�
+     */
+    public boolean isSubListValue(T vo)
+    {
+        return StringUtils.isNotNull(subFields) && subFields.size() > 0 && StringUtils.isNotNull(getListCellValue(vo)) && getListCellValue(vo).size() > 0;
+    }
+
+    /**
+     * 鑾峰彇闆嗗悎鐨勫��
+     */
+    public Collection<?> getListCellValue(Object obj)
+    {
+        Object value;
+        try
+        {
+            value = subMethod.invoke(obj, new Object[] {});
+        }
+        catch (Exception e)
+        {
+            return new ArrayList<Object>();
+        }
+        return (Collection<?>) value;
+    }
+
+    /**
+     * 鑾峰彇瀵硅薄鐨勫瓙鍒楄〃鏂规硶
+     * 
+     * @param name 鍚嶇О
+     * @param pojoClass 绫诲璞�
+     * @return 瀛愬垪琛ㄦ柟娉�
+     */
+    public Method getSubMethod(String name, Class<?> pojoClass)
+    {
+        StringBuffer getMethodName = new StringBuffer("get");
+        getMethodName.append(name.substring(0, 1).toUpperCase());
+        getMethodName.append(name.substring(1));
+        Method method = null;
+        try
+        {
+            method = pojoClass.getMethod(getMethodName.toString(), new Class[] {});
+        }
+        catch (Exception e)
+        {
+            log.error("鑾峰彇瀵硅薄寮傚父{}", e.getMessage());
+        }
+        return method;
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/utils/reflect/ReflectUtils.java b/jcdm-common/src/main/java/com/jcdm/common/utils/reflect/ReflectUtils.java
new file mode 100644
index 0000000..9a75fab
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/utils/reflect/ReflectUtils.java
@@ -0,0 +1,410 @@
+package com.jcdm.common.utils.reflect;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Date;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.Validate;
+import org.apache.poi.ss.usermodel.DateUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.jcdm.common.core.text.Convert;
+import com.jcdm.common.utils.DateUtils;
+
+/**
+ * 鍙嶅皠宸ュ叿绫�. 鎻愪緵璋冪敤getter/setter鏂规硶, 璁块棶绉佹湁鍙橀噺, 璋冪敤绉佹湁鏂规硶, 鑾峰彇娉涘瀷绫诲瀷Class, 琚獳OP杩囩殑鐪熷疄绫荤瓑宸ュ叿鍑芥暟.
+ * 
+ * @author jc
+ */
+@SuppressWarnings("rawtypes")
+public class ReflectUtils
+{
+    private static final String SETTER_PREFIX = "set";
+
+    private static final String GETTER_PREFIX = "get";
+
+    private static final String CGLIB_CLASS_SEPARATOR = "$$";
+
+    private static Logger logger = LoggerFactory.getLogger(ReflectUtils.class);
+
+    /**
+     * 璋冪敤Getter鏂规硶.
+     * 鏀寔澶氱骇锛屽锛氬璞″悕.瀵硅薄鍚�.鏂规硶
+     */
+    @SuppressWarnings("unchecked")
+    public static <E> E invokeGetter(Object obj, String propertyName)
+    {
+        Object object = obj;
+        for (String name : StringUtils.split(propertyName, "."))
+        {
+            String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name);
+            object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {});
+        }
+        return (E) object;
+    }
+
+    /**
+     * 璋冪敤Setter鏂规硶, 浠呭尮閰嶆柟娉曞悕銆�
+     * 鏀寔澶氱骇锛屽锛氬璞″悕.瀵硅薄鍚�.鏂规硶
+     */
+    public static <E> void invokeSetter(Object obj, String propertyName, E value)
+    {
+        Object object = obj;
+        String[] names = StringUtils.split(propertyName, ".");
+        for (int i = 0; i < names.length; i++)
+        {
+            if (i < names.length - 1)
+            {
+                String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]);
+                object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {});
+            }
+            else
+            {
+                String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]);
+                invokeMethodByName(object, setterMethodName, new Object[] { value });
+            }
+        }
+    }
+
+    /**
+     * 鐩存帴璇诲彇瀵硅薄灞炴�у��, 鏃犺private/protected淇グ绗�, 涓嶇粡杩噂etter鍑芥暟.
+     */
+    @SuppressWarnings("unchecked")
+    public static <E> E getFieldValue(final Object obj, final String fieldName)
+    {
+        Field field = getAccessibleField(obj, fieldName);
+        if (field == null)
+        {
+            logger.debug("鍦� [" + obj.getClass() + "] 涓紝娌℃湁鎵惧埌 [" + fieldName + "] 瀛楁 ");
+            return null;
+        }
+        E result = null;
+        try
+        {
+            result = (E) field.get(obj);
+        }
+        catch (IllegalAccessException e)
+        {
+            logger.error("涓嶅彲鑳芥姏鍑虹殑寮傚父{}", e.getMessage());
+        }
+        return result;
+    }
+
+    /**
+     * 鐩存帴璁剧疆瀵硅薄灞炴�у��, 鏃犺private/protected淇グ绗�, 涓嶇粡杩噑etter鍑芥暟.
+     */
+    public static <E> void setFieldValue(final Object obj, final String fieldName, final E value)
+    {
+        Field field = getAccessibleField(obj, fieldName);
+        if (field == null)
+        {
+            // throw new IllegalArgumentException("鍦� [" + obj.getClass() + "] 涓紝娌℃湁鎵惧埌 [" + fieldName + "] 瀛楁 ");
+            logger.debug("鍦� [" + obj.getClass() + "] 涓紝娌℃湁鎵惧埌 [" + fieldName + "] 瀛楁 ");
+            return;
+        }
+        try
+        {
+            field.set(obj, value);
+        }
+        catch (IllegalAccessException e)
+        {
+            logger.error("涓嶅彲鑳芥姏鍑虹殑寮傚父: {}", e.getMessage());
+        }
+    }
+
+    /**
+     * 鐩存帴璋冪敤瀵硅薄鏂规硶, 鏃犺private/protected淇グ绗�.
+     * 鐢ㄤ簬涓�娆℃�ц皟鐢ㄧ殑鎯呭喌锛屽惁鍒欏簲浣跨敤getAccessibleMethod()鍑芥暟鑾峰緱Method鍚庡弽澶嶈皟鐢�.
+     * 鍚屾椂鍖归厤鏂规硶鍚�+鍙傛暟绫诲瀷锛�
+     */
+    @SuppressWarnings("unchecked")
+    public static <E> E invokeMethod(final Object obj, final String methodName, final Class<?>[] parameterTypes,
+            final Object[] args)
+    {
+        if (obj == null || methodName == null)
+        {
+            return null;
+        }
+        Method method = getAccessibleMethod(obj, methodName, parameterTypes);
+        if (method == null)
+        {
+            logger.debug("鍦� [" + obj.getClass() + "] 涓紝娌℃湁鎵惧埌 [" + methodName + "] 鏂规硶 ");
+            return null;
+        }
+        try
+        {
+            return (E) method.invoke(obj, args);
+        }
+        catch (Exception e)
+        {
+            String msg = "method: " + method + ", obj: " + obj + ", args: " + args + "";
+            throw convertReflectionExceptionToUnchecked(msg, e);
+        }
+    }
+
+    /**
+     * 鐩存帴璋冪敤瀵硅薄鏂规硶, 鏃犺private/protected淇グ绗︼紝
+     * 鐢ㄤ簬涓�娆℃�ц皟鐢ㄧ殑鎯呭喌锛屽惁鍒欏簲浣跨敤getAccessibleMethodByName()鍑芥暟鑾峰緱Method鍚庡弽澶嶈皟鐢�.
+     * 鍙尮閰嶅嚱鏁板悕锛屽鏋滄湁澶氫釜鍚屽悕鍑芥暟璋冪敤绗竴涓��
+     */
+    @SuppressWarnings("unchecked")
+    public static <E> E invokeMethodByName(final Object obj, final String methodName, final Object[] args)
+    {
+        Method method = getAccessibleMethodByName(obj, methodName, args.length);
+        if (method == null)
+        {
+            // 濡傛灉涓虹┖涓嶆姤閿欙紝鐩存帴杩斿洖绌恒��
+            logger.debug("鍦� [" + obj.getClass() + "] 涓紝娌℃湁鎵惧埌 [" + methodName + "] 鏂规硶 ");
+            return null;
+        }
+        try
+        {
+            // 绫诲瀷杞崲锛堝皢鍙傛暟鏁版嵁绫诲瀷杞崲涓虹洰鏍囨柟娉曞弬鏁扮被鍨嬶級
+            Class<?>[] cs = method.getParameterTypes();
+            for (int i = 0; i < cs.length; i++)
+            {
+                if (args[i] != null && !args[i].getClass().equals(cs[i]))
+                {
+                    if (cs[i] == String.class)
+                    {
+                        args[i] = Convert.toStr(args[i]);
+                        if (StringUtils.endsWith((String) args[i], ".0"))
+                        {
+                            args[i] = StringUtils.substringBefore((String) args[i], ".0");
+                        }
+                    }
+                    else if (cs[i] == Integer.class)
+                    {
+                        args[i] = Convert.toInt(args[i]);
+                    }
+                    else if (cs[i] == Long.class)
+                    {
+                        args[i] = Convert.toLong(args[i]);
+                    }
+                    else if (cs[i] == Double.class)
+                    {
+                        args[i] = Convert.toDouble(args[i]);
+                    }
+                    else if (cs[i] == Float.class)
+                    {
+                        args[i] = Convert.toFloat(args[i]);
+                    }
+                    else if (cs[i] == Date.class)
+                    {
+                        if (args[i] instanceof String)
+                        {
+                            args[i] = DateUtils.parseDate(args[i]);
+                        }
+                        else
+                        {
+                            args[i] = DateUtil.getJavaDate((Double) args[i]);
+                        }
+                    }
+                    else if (cs[i] == boolean.class || cs[i] == Boolean.class)
+                    {
+                        args[i] = Convert.toBool(args[i]);
+                    }
+                }
+            }
+            return (E) method.invoke(obj, args);
+        }
+        catch (Exception e)
+        {
+            String msg = "method: " + method + ", obj: " + obj + ", args: " + args + "";
+            throw convertReflectionExceptionToUnchecked(msg, e);
+        }
+    }
+
+    /**
+     * 寰幆鍚戜笂杞瀷, 鑾峰彇瀵硅薄鐨凞eclaredField, 骞跺己鍒惰缃负鍙闂�.
+     * 濡傚悜涓婅浆鍨嬪埌Object浠嶆棤娉曟壘鍒�, 杩斿洖null.
+     */
+    public static Field getAccessibleField(final Object obj, final String fieldName)
+    {
+        // 涓虹┖涓嶆姤閿欍�傜洿鎺ヨ繑鍥� null
+        if (obj == null)
+        {
+            return null;
+        }
+        Validate.notBlank(fieldName, "fieldName can't be blank");
+        for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass())
+        {
+            try
+            {
+                Field field = superClass.getDeclaredField(fieldName);
+                makeAccessible(field);
+                return field;
+            }
+            catch (NoSuchFieldException e)
+            {
+                continue;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 寰幆鍚戜笂杞瀷, 鑾峰彇瀵硅薄鐨凞eclaredMethod,骞跺己鍒惰缃负鍙闂�.
+     * 濡傚悜涓婅浆鍨嬪埌Object浠嶆棤娉曟壘鍒�, 杩斿洖null.
+     * 鍖归厤鍑芥暟鍚�+鍙傛暟绫诲瀷銆�
+     * 鐢ㄤ簬鏂规硶闇�瑕佽澶氭璋冪敤鐨勬儏鍐�. 鍏堜娇鐢ㄦ湰鍑芥暟鍏堝彇寰桵ethod,鐒跺悗璋冪敤Method.invoke(Object obj, Object... args)
+     */
+    public static Method getAccessibleMethod(final Object obj, final String methodName,
+            final Class<?>... parameterTypes)
+    {
+        // 涓虹┖涓嶆姤閿欍�傜洿鎺ヨ繑鍥� null
+        if (obj == null)
+        {
+            return null;
+        }
+        Validate.notBlank(methodName, "methodName can't be blank");
+        for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass())
+        {
+            try
+            {
+                Method method = searchType.getDeclaredMethod(methodName, parameterTypes);
+                makeAccessible(method);
+                return method;
+            }
+            catch (NoSuchMethodException e)
+            {
+                continue;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 寰幆鍚戜笂杞瀷, 鑾峰彇瀵硅薄鐨凞eclaredMethod,骞跺己鍒惰缃负鍙闂�.
+     * 濡傚悜涓婅浆鍨嬪埌Object浠嶆棤娉曟壘鍒�, 杩斿洖null.
+     * 鍙尮閰嶅嚱鏁板悕銆�
+     * 鐢ㄤ簬鏂规硶闇�瑕佽澶氭璋冪敤鐨勬儏鍐�. 鍏堜娇鐢ㄦ湰鍑芥暟鍏堝彇寰桵ethod,鐒跺悗璋冪敤Method.invoke(Object obj, Object... args)
+     */
+    public static Method getAccessibleMethodByName(final Object obj, final String methodName, int argsNum)
+    {
+        // 涓虹┖涓嶆姤閿欍�傜洿鎺ヨ繑鍥� null
+        if (obj == null)
+        {
+            return null;
+        }
+        Validate.notBlank(methodName, "methodName can't be blank");
+        for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass())
+        {
+            Method[] methods = searchType.getDeclaredMethods();
+            for (Method method : methods)
+            {
+                if (method.getName().equals(methodName) && method.getParameterTypes().length == argsNum)
+                {
+                    makeAccessible(method);
+                    return method;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 鏀瑰彉private/protected鐨勬柟娉曚负public锛屽敖閲忎笉璋冪敤瀹為檯鏀瑰姩鐨勮鍙ワ紝閬垮厤JDK鐨凷ecurityManager鎶辨�ㄣ��
+     */
+    public static void makeAccessible(Method method)
+    {
+        if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers()))
+                && !method.isAccessible())
+        {
+            method.setAccessible(true);
+        }
+    }
+
+    /**
+     * 鏀瑰彉private/protected鐨勬垚鍛樺彉閲忎负public锛屽敖閲忎笉璋冪敤瀹為檯鏀瑰姩鐨勮鍙ワ紝閬垮厤JDK鐨凷ecurityManager鎶辨�ㄣ��
+     */
+    public static void makeAccessible(Field field)
+    {
+        if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers())
+                || Modifier.isFinal(field.getModifiers())) && !field.isAccessible())
+        {
+            field.setAccessible(true);
+        }
+    }
+
+    /**
+     * 閫氳繃鍙嶅皠, 鑾峰緱Class瀹氫箟涓0鏄庣殑娉涘瀷鍙傛暟鐨勭被鍨�, 娉ㄦ剰娉涘瀷蹇呴』瀹氫箟鍦ㄧ埗绫诲
+     * 濡傛棤娉曟壘鍒�, 杩斿洖Object.class.
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> Class<T> getClassGenricType(final Class clazz)
+    {
+        return getClassGenricType(clazz, 0);
+    }
+
+    /**
+     * 閫氳繃鍙嶅皠, 鑾峰緱Class瀹氫箟涓0鏄庣殑鐖剁被鐨勬硾鍨嬪弬鏁扮殑绫诲瀷.
+     * 濡傛棤娉曟壘鍒�, 杩斿洖Object.class.
+     */
+    public static Class getClassGenricType(final Class clazz, final int index)
+    {
+        Type genType = clazz.getGenericSuperclass();
+
+        if (!(genType instanceof ParameterizedType))
+        {
+            logger.debug(clazz.getSimpleName() + "'s superclass not ParameterizedType");
+            return Object.class;
+        }
+
+        Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
+
+        if (index >= params.length || index < 0)
+        {
+            logger.debug("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: "
+                    + params.length);
+            return Object.class;
+        }
+        if (!(params[index] instanceof Class))
+        {
+            logger.debug(clazz.getSimpleName() + " not set the actual class on superclass generic parameter");
+            return Object.class;
+        }
+
+        return (Class) params[index];
+    }
+
+    public static Class<?> getUserClass(Object instance)
+    {
+        if (instance == null)
+        {
+            throw new RuntimeException("Instance must not be null");
+        }
+        Class clazz = instance.getClass();
+        if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR))
+        {
+            Class<?> superClass = clazz.getSuperclass();
+            if (superClass != null && !Object.class.equals(superClass))
+            {
+                return superClass;
+            }
+        }
+        return clazz;
+
+    }
+
+    /**
+     * 灏嗗弽灏勬椂鐨刢hecked exception杞崲涓簎nchecked exception.
+     */
+    public static RuntimeException convertReflectionExceptionToUnchecked(String msg, Exception e)
+    {
+        if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException
+                || e instanceof NoSuchMethodException)
+        {
+            return new IllegalArgumentException(msg, e);
+        }
+        else if (e instanceof InvocationTargetException)
+        {
+            return new RuntimeException(msg, ((InvocationTargetException) e).getTargetException());
+        }
+        return new RuntimeException(msg, e);
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/utils/sign/Base64.java b/jcdm-common/src/main/java/com/jcdm/common/utils/sign/Base64.java
new file mode 100644
index 0000000..7a679e1
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/utils/sign/Base64.java
@@ -0,0 +1,291 @@
+package com.jcdm.common.utils.sign;
+
+/**
+ * Base64宸ュ叿绫�
+ * 
+ * @author jc
+ */
+public final class Base64
+{
+    static private final int     BASELENGTH           = 128;
+    static private final int     LOOKUPLENGTH         = 64;
+    static private final int     TWENTYFOURBITGROUP   = 24;
+    static private final int     EIGHTBIT             = 8;
+    static private final int     SIXTEENBIT           = 16;
+    static private final int     FOURBYTE             = 4;
+    static private final int     SIGN                 = -128;
+    static private final char    PAD                  = '=';
+    static final private byte[]  base64Alphabet       = new byte[BASELENGTH];
+    static final private char[]  lookUpBase64Alphabet = new char[LOOKUPLENGTH];
+
+    static
+    {
+        for (int i = 0; i < BASELENGTH; ++i)
+        {
+            base64Alphabet[i] = -1;
+        }
+        for (int i = 'Z'; i >= 'A'; i--)
+        {
+            base64Alphabet[i] = (byte) (i - 'A');
+        }
+        for (int i = 'z'; i >= 'a'; i--)
+        {
+            base64Alphabet[i] = (byte) (i - 'a' + 26);
+        }
+
+        for (int i = '9'; i >= '0'; i--)
+        {
+            base64Alphabet[i] = (byte) (i - '0' + 52);
+        }
+
+        base64Alphabet['+'] = 62;
+        base64Alphabet['/'] = 63;
+
+        for (int i = 0; i <= 25; i++)
+        {
+            lookUpBase64Alphabet[i] = (char) ('A' + i);
+        }
+
+        for (int i = 26, j = 0; i <= 51; i++, j++)
+        {
+            lookUpBase64Alphabet[i] = (char) ('a' + j);
+        }
+
+        for (int i = 52, j = 0; i <= 61; i++, j++)
+        {
+            lookUpBase64Alphabet[i] = (char) ('0' + j);
+        }
+        lookUpBase64Alphabet[62] = (char) '+';
+        lookUpBase64Alphabet[63] = (char) '/';
+    }
+
+    private static boolean isWhiteSpace(char octect)
+    {
+        return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
+    }
+
+    private static boolean isPad(char octect)
+    {
+        return (octect == PAD);
+    }
+
+    private static boolean isData(char octect)
+    {
+        return (octect < BASELENGTH && base64Alphabet[octect] != -1);
+    }
+
+    /**
+     * Encodes hex octects into Base64
+     *
+     * @param binaryData Array containing binaryData
+     * @return Encoded Base64 array
+     */
+    public static String encode(byte[] binaryData)
+    {
+        if (binaryData == null)
+        {
+            return null;
+        }
+
+        int lengthDataBits = binaryData.length * EIGHTBIT;
+        if (lengthDataBits == 0)
+        {
+            return "";
+        }
+
+        int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
+        int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
+        int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1 : numberTriplets;
+        char encodedData[] = null;
+
+        encodedData = new char[numberQuartet * 4];
+
+        byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
+
+        int encodedIndex = 0;
+        int dataIndex = 0;
+
+        for (int i = 0; i < numberTriplets; i++)
+        {
+            b1 = binaryData[dataIndex++];
+            b2 = binaryData[dataIndex++];
+            b3 = binaryData[dataIndex++];
+
+            l = (byte) (b2 & 0x0f);
+            k = (byte) (b1 & 0x03);
+
+            byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
+            byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
+            byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc);
+
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3];
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f];
+        }
+
+        // form integral number of 6-bit groups
+        if (fewerThan24bits == EIGHTBIT)
+        {
+            b1 = binaryData[dataIndex];
+            k = (byte) (b1 & 0x03);
+            byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4];
+            encodedData[encodedIndex++] = PAD;
+            encodedData[encodedIndex++] = PAD;
+        }
+        else if (fewerThan24bits == SIXTEENBIT)
+        {
+            b1 = binaryData[dataIndex];
+            b2 = binaryData[dataIndex + 1];
+            l = (byte) (b2 & 0x0f);
+            k = (byte) (b1 & 0x03);
+
+            byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
+            byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
+
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2];
+            encodedData[encodedIndex++] = PAD;
+        }
+        return new String(encodedData);
+    }
+
+    /**
+     * Decodes Base64 data into octects
+     *
+     * @param encoded string containing Base64 data
+     * @return Array containind decoded data.
+     */
+    public static byte[] decode(String encoded)
+    {
+        if (encoded == null)
+        {
+            return null;
+        }
+
+        char[] base64Data = encoded.toCharArray();
+        // remove white spaces
+        int len = removeWhiteSpace(base64Data);
+
+        if (len % FOURBYTE != 0)
+        {
+            return null;// should be divisible by four
+        }
+
+        int numberQuadruple = (len / FOURBYTE);
+
+        if (numberQuadruple == 0)
+        {
+            return new byte[0];
+        }
+
+        byte decodedData[] = null;
+        byte b1 = 0, b2 = 0, b3 = 0, b4 = 0;
+        char d1 = 0, d2 = 0, d3 = 0, d4 = 0;
+
+        int i = 0;
+        int encodedIndex = 0;
+        int dataIndex = 0;
+        decodedData = new byte[(numberQuadruple) * 3];
+
+        for (; i < numberQuadruple - 1; i++)
+        {
+
+            if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))
+                    || !isData((d3 = base64Data[dataIndex++])) || !isData((d4 = base64Data[dataIndex++])))
+            {
+                return null;
+            } // if found "no data" just return null
+
+            b1 = base64Alphabet[d1];
+            b2 = base64Alphabet[d2];
+            b3 = base64Alphabet[d3];
+            b4 = base64Alphabet[d4];
+
+            decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
+            decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
+            decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
+        }
+
+        if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++])))
+        {
+            return null;// if found "no data" just return null
+        }
+
+        b1 = base64Alphabet[d1];
+        b2 = base64Alphabet[d2];
+
+        d3 = base64Data[dataIndex++];
+        d4 = base64Data[dataIndex++];
+        if (!isData((d3)) || !isData((d4)))
+        {// Check if they are PAD characters
+            if (isPad(d3) && isPad(d4))
+            {
+                if ((b2 & 0xf) != 0)// last 4 bits should be zero
+                {
+                    return null;
+                }
+                byte[] tmp = new byte[i * 3 + 1];
+                System.arraycopy(decodedData, 0, tmp, 0, i * 3);
+                tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
+                return tmp;
+            }
+            else if (!isPad(d3) && isPad(d4))
+            {
+                b3 = base64Alphabet[d3];
+                if ((b3 & 0x3) != 0)// last 2 bits should be zero
+                {
+                    return null;
+                }
+                byte[] tmp = new byte[i * 3 + 2];
+                System.arraycopy(decodedData, 0, tmp, 0, i * 3);
+                tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
+                tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
+                return tmp;
+            }
+            else
+            {
+                return null;
+            }
+        }
+        else
+        { // No PAD e.g 3cQl
+            b3 = base64Alphabet[d3];
+            b4 = base64Alphabet[d4];
+            decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
+            decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
+            decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
+
+        }
+        return decodedData;
+    }
+
+    /**
+     * remove WhiteSpace from MIME containing encoded Base64 data.
+     *
+     * @param data the byte array of base64 data (with WS)
+     * @return the new length
+     */
+    private static int removeWhiteSpace(char[] data)
+    {
+        if (data == null)
+        {
+            return 0;
+        }
+
+        // count characters that's not whitespace
+        int newSize = 0;
+        int len = data.length;
+        for (int i = 0; i < len; i++)
+        {
+            if (!isWhiteSpace(data[i]))
+            {
+                data[newSize++] = data[i];
+            }
+        }
+        return newSize;
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/utils/sign/Md5Utils.java b/jcdm-common/src/main/java/com/jcdm/common/utils/sign/Md5Utils.java
new file mode 100644
index 0000000..40a2cef
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/utils/sign/Md5Utils.java
@@ -0,0 +1,67 @@
+package com.jcdm.common.utils.sign;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Md5鍔犲瘑鏂规硶
+ * 
+ * @author jc
+ */
+public class Md5Utils
+{
+    private static final Logger log = LoggerFactory.getLogger(Md5Utils.class);
+
+    private static byte[] md5(String s)
+    {
+        MessageDigest algorithm;
+        try
+        {
+            algorithm = MessageDigest.getInstance("MD5");
+            algorithm.reset();
+            algorithm.update(s.getBytes("UTF-8"));
+            byte[] messageDigest = algorithm.digest();
+            return messageDigest;
+        }
+        catch (Exception e)
+        {
+            log.error("MD5 Error...", e);
+        }
+        return null;
+    }
+
+    private static final String toHex(byte hash[])
+    {
+        if (hash == null)
+        {
+            return null;
+        }
+        StringBuffer buf = new StringBuffer(hash.length * 2);
+        int i;
+
+        for (i = 0; i < hash.length; i++)
+        {
+            if ((hash[i] & 0xff) < 0x10)
+            {
+                buf.append("0");
+            }
+            buf.append(Long.toString(hash[i] & 0xff, 16));
+        }
+        return buf.toString();
+    }
+
+    public static String hash(String s)
+    {
+        try
+        {
+            return new String(toHex(md5(s)).getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8);
+        }
+        catch (Exception e)
+        {
+            log.error("not supported charset...{}", e);
+            return s;
+        }
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/utils/spring/SpringUtils.java b/jcdm-common/src/main/java/com/jcdm/common/utils/spring/SpringUtils.java
new file mode 100644
index 0000000..abb9ad0
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/utils/spring/SpringUtils.java
@@ -0,0 +1,158 @@
+package com.jcdm.common.utils.spring;
+
+import org.springframework.aop.framework.AopContext;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+import com.jcdm.common.utils.StringUtils;
+
+/**
+ * spring宸ュ叿绫� 鏂逛究鍦ㄩ潪spring绠$悊鐜涓幏鍙朾ean
+ * 
+ * @author jc
+ */
+@Component
+public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware 
+{
+    /** Spring搴旂敤涓婁笅鏂囩幆澧� */
+    private static ConfigurableListableBeanFactory beanFactory;
+
+    private static ApplicationContext applicationContext;
+
+    @Override
+    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException 
+    {
+        SpringUtils.beanFactory = beanFactory;
+    }
+
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException 
+    {
+        SpringUtils.applicationContext = applicationContext;
+    }
+
+    /**
+     * 鑾峰彇瀵硅薄
+     *
+     * @param name
+     * @return Object 涓�涓互鎵�缁欏悕瀛楁敞鍐岀殑bean鐨勫疄渚�
+     * @throws org.springframework.beans.BeansException
+     *
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T getBean(String name) throws BeansException
+    {
+        return (T) beanFactory.getBean(name);
+    }
+
+    /**
+     * 鑾峰彇绫诲瀷涓簉equiredType鐨勫璞�
+     *
+     * @param clz
+     * @return
+     * @throws org.springframework.beans.BeansException
+     *
+     */
+    public static <T> T getBean(Class<T> clz) throws BeansException
+    {
+        T result = (T) beanFactory.getBean(clz);
+        return result;
+    }
+
+    /**
+     * 濡傛灉BeanFactory鍖呭惈涓�涓笌鎵�缁欏悕绉板尮閰嶇殑bean瀹氫箟锛屽垯杩斿洖true
+     *
+     * @param name
+     * @return boolean
+     */
+    public static boolean containsBean(String name)
+    {
+        return beanFactory.containsBean(name);
+    }
+
+    /**
+     * 鍒ゆ柇浠ョ粰瀹氬悕瀛楁敞鍐岀殑bean瀹氫箟鏄竴涓猻ingleton杩樻槸涓�涓猵rototype銆� 濡傛灉涓庣粰瀹氬悕瀛楃浉搴旂殑bean瀹氫箟娌℃湁琚壘鍒帮紝灏嗕細鎶涘嚭涓�涓紓甯革紙NoSuchBeanDefinitionException锛�
+     *
+     * @param name
+     * @return boolean
+     * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
+     *
+     */
+    public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException
+    {
+        return beanFactory.isSingleton(name);
+    }
+
+    /**
+     * @param name
+     * @return Class 娉ㄥ唽瀵硅薄鐨勭被鍨�
+     * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
+     *
+     */
+    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException
+    {
+        return beanFactory.getType(name);
+    }
+
+    /**
+     * 濡傛灉缁欏畾鐨刡ean鍚嶅瓧鍦╞ean瀹氫箟涓湁鍒悕锛屽垯杩斿洖杩欎簺鍒悕
+     *
+     * @param name
+     * @return
+     * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
+     *
+     */
+    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException
+    {
+        return beanFactory.getAliases(name);
+    }
+
+    /**
+     * 鑾峰彇aop浠g悊瀵硅薄
+     * 
+     * @param invoker
+     * @return
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T getAopProxy(T invoker)
+    {
+        return (T) AopContext.currentProxy();
+    }
+
+    /**
+     * 鑾峰彇褰撳墠鐨勭幆澧冮厤缃紝鏃犻厤缃繑鍥瀗ull
+     *
+     * @return 褰撳墠鐨勭幆澧冮厤缃�
+     */
+    public static String[] getActiveProfiles()
+    {
+        return applicationContext.getEnvironment().getActiveProfiles();
+    }
+
+    /**
+     * 鑾峰彇褰撳墠鐨勭幆澧冮厤缃紝褰撴湁澶氫釜鐜閰嶇疆鏃讹紝鍙幏鍙栫涓�涓�
+     *
+     * @return 褰撳墠鐨勭幆澧冮厤缃�
+     */
+    public static String getActiveProfile()
+    {
+        final String[] activeProfiles = getActiveProfiles();
+        return StringUtils.isNotEmpty(activeProfiles) ? activeProfiles[0] : null;
+    }
+
+    /**
+     * 鑾峰彇閰嶇疆鏂囦欢涓殑鍊�
+     *
+     * @param key 閰嶇疆鏂囦欢鐨刱ey
+     * @return 褰撳墠鐨勯厤缃枃浠剁殑鍊�
+     *
+     */
+    public static String getRequiredProperty(String key)
+    {
+        return applicationContext.getEnvironment().getRequiredProperty(key);
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/utils/sql/SqlUtil.java b/jcdm-common/src/main/java/com/jcdm/common/utils/sql/SqlUtil.java
new file mode 100644
index 0000000..61979e4
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/utils/sql/SqlUtil.java
@@ -0,0 +1,70 @@
+package com.jcdm.common.utils.sql;
+
+import com.jcdm.common.exception.UtilException;
+import com.jcdm.common.utils.StringUtils;
+
+/**
+ * sql鎿嶄綔宸ュ叿绫�
+ * 
+ * @author jc
+ */
+public class SqlUtil
+{
+    /**
+     * 瀹氫箟甯哥敤鐨� sql鍏抽敭瀛�
+     */
+    public static String SQL_REGEX = "and |extractvalue|updatexml|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |+|user()";
+
+    /**
+     * 浠呮敮鎸佸瓧姣嶃�佹暟瀛椼�佷笅鍒掔嚎銆佺┖鏍笺�侀�楀彿銆佸皬鏁扮偣锛堟敮鎸佸涓瓧娈垫帓搴忥級
+     */
+    public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+";
+
+    /**
+     * 闄愬埗orderBy鏈�澶ч暱搴�
+     */
+    private static final int ORDER_BY_MAX_LENGTH = 500;
+
+    /**
+     * 妫�鏌ュ瓧绗︼紝闃叉娉ㄥ叆缁曡繃
+     */
+    public static String escapeOrderBySql(String value)
+    {
+        if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value))
+        {
+            throw new UtilException("鍙傛暟涓嶇鍚堣鑼冿紝涓嶈兘杩涜鏌ヨ");
+        }
+        if (StringUtils.length(value) > ORDER_BY_MAX_LENGTH)
+        {
+            throw new UtilException("鍙傛暟宸茶秴杩囨渶澶ч檺鍒讹紝涓嶈兘杩涜鏌ヨ");
+        }
+        return value;
+    }
+
+    /**
+     * 楠岃瘉 order by 璇硶鏄惁绗﹀悎瑙勮寖
+     */
+    public static boolean isValidOrderBySql(String value)
+    {
+        return value.matches(SQL_PATTERN);
+    }
+
+    /**
+     * SQL鍏抽敭瀛楁鏌�
+     */
+    public static void filterKeyword(String value)
+    {
+        if (StringUtils.isEmpty(value))
+        {
+            return;
+        }
+        String[] sqlKeywords = StringUtils.split(SQL_REGEX, "\\|");
+        for (String sqlKeyword : sqlKeywords)
+        {
+            if (StringUtils.indexOfIgnoreCase(value, sqlKeyword) > -1)
+            {
+                throw new UtilException("鍙傛暟瀛樺湪SQL娉ㄥ叆椋庨櫓");
+            }
+        }
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/utils/uuid/IdUtils.java b/jcdm-common/src/main/java/com/jcdm/common/utils/uuid/IdUtils.java
new file mode 100644
index 0000000..da043a6
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/utils/uuid/IdUtils.java
@@ -0,0 +1,49 @@
+package com.jcdm.common.utils.uuid;
+
+/**
+ * ID鐢熸垚鍣ㄥ伐鍏风被
+ * 
+ * @author jc
+ */
+public class IdUtils
+{
+    /**
+     * 鑾峰彇闅忔満UUID
+     * 
+     * @return 闅忔満UUID
+     */
+    public static String randomUUID()
+    {
+        return UUID.randomUUID().toString();
+    }
+
+    /**
+     * 绠�鍖栫殑UUID锛屽幓鎺変簡妯嚎
+     * 
+     * @return 绠�鍖栫殑UUID锛屽幓鎺変簡妯嚎
+     */
+    public static String simpleUUID()
+    {
+        return UUID.randomUUID().toString(true);
+    }
+
+    /**
+     * 鑾峰彇闅忔満UUID锛屼娇鐢ㄦ�ц兘鏇村ソ鐨凾hreadLocalRandom鐢熸垚UUID
+     * 
+     * @return 闅忔満UUID
+     */
+    public static String fastUUID()
+    {
+        return UUID.fastUUID().toString();
+    }
+
+    /**
+     * 绠�鍖栫殑UUID锛屽幓鎺変簡妯嚎锛屼娇鐢ㄦ�ц兘鏇村ソ鐨凾hreadLocalRandom鐢熸垚UUID
+     * 
+     * @return 绠�鍖栫殑UUID锛屽幓鎺変簡妯嚎
+     */
+    public static String fastSimpleUUID()
+    {
+        return UUID.fastUUID().toString(true);
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/utils/uuid/Seq.java b/jcdm-common/src/main/java/com/jcdm/common/utils/uuid/Seq.java
new file mode 100644
index 0000000..fddde9e
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/utils/uuid/Seq.java
@@ -0,0 +1,86 @@
+package com.jcdm.common.utils.uuid;
+
+import java.util.concurrent.atomic.AtomicInteger;
+import com.jcdm.common.utils.DateUtils;
+import com.jcdm.common.utils.StringUtils;
+
+/**
+ * @author jc 搴忓垪鐢熸垚绫�
+ */
+public class Seq
+{
+    // 閫氱敤搴忓垪绫诲瀷
+    public static final String commSeqType = "COMMON";
+
+    // 涓婁紶搴忓垪绫诲瀷
+    public static final String uploadSeqType = "UPLOAD";
+
+    // 閫氱敤鎺ュ彛搴忓垪鏁�
+    private static AtomicInteger commSeq = new AtomicInteger(1);
+
+    // 涓婁紶鎺ュ彛搴忓垪鏁�
+    private static AtomicInteger uploadSeq = new AtomicInteger(1);
+
+    // 鏈哄櫒鏍囪瘑
+    private static final String machineCode = "A";
+
+    /**
+     * 鑾峰彇閫氱敤搴忓垪鍙�
+     * 
+     * @return 搴忓垪鍊�
+     */
+    public static String getId()
+    {
+        return getId(commSeqType);
+    }
+    
+    /**
+     * 榛樿16浣嶅簭鍒楀彿 yyMMddHHmmss + 涓�浣嶆満鍣ㄦ爣璇� + 3闀垮害寰幆閫掑瀛楃涓�
+     * 
+     * @return 搴忓垪鍊�
+     */
+    public static String getId(String type)
+    {
+        AtomicInteger atomicInt = commSeq;
+        if (uploadSeqType.equals(type))
+        {
+            atomicInt = uploadSeq;
+        }
+        return getId(atomicInt, 3);
+    }
+
+    /**
+     * 閫氱敤鎺ュ彛搴忓垪鍙� yyMMddHHmmss + 涓�浣嶆満鍣ㄦ爣璇� + length闀垮害寰幆閫掑瀛楃涓�
+     * 
+     * @param atomicInt 搴忓垪鏁�
+     * @param length 鏁板�奸暱搴�
+     * @return 搴忓垪鍊�
+     */
+    public static String getId(AtomicInteger atomicInt, int length)
+    {
+        String result = DateUtils.dateTimeNow();
+        result += machineCode;
+        result += getSeq(atomicInt, length);
+        return result;
+    }
+
+    /**
+     * 搴忓垪寰幆閫掑瀛楃涓瞇1, 10 鐨� (length)骞傛鏂�), 鐢�0宸﹁ˉ榻恖ength浣嶆暟
+     * 
+     * @return 搴忓垪鍊�
+     */
+    private synchronized static String getSeq(AtomicInteger atomicInt, int length)
+    {
+        // 鍏堝彇鍊煎啀+1
+        int value = atomicInt.getAndIncrement();
+
+        // 濡傛灉鏇存柊鍚庡��>=10 鐨� (length)骞傛鏂瑰垯閲嶇疆涓�1
+        int maxSeq = (int) Math.pow(10, length);
+        if (atomicInt.get() >= maxSeq)
+        {
+            atomicInt.set(1);
+        }
+        // 杞瓧绗︿覆锛岀敤0宸﹁ˉ榻�
+        return StringUtils.padl(value, length);
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/utils/uuid/UUID.java b/jcdm-common/src/main/java/com/jcdm/common/utils/uuid/UUID.java
new file mode 100644
index 0000000..651f5b5
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/utils/uuid/UUID.java
@@ -0,0 +1,484 @@
+package com.jcdm.common.utils.uuid;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.Random;
+import java.util.concurrent.ThreadLocalRandom;
+import com.jcdm.common.exception.UtilException;
+
+/**
+ * 鎻愪緵閫氱敤鍞竴璇嗗埆鐮侊紙universally unique identifier锛夛紙UUID锛夊疄鐜�
+ *
+ * @author jc
+ */
+public final class UUID implements java.io.Serializable, Comparable<UUID>
+{
+    private static final long serialVersionUID = -1185015143654744140L;
+
+    /**
+     * SecureRandom 鐨勫崟渚�
+     *
+     */
+    private static class Holder
+    {
+        static final SecureRandom numberGenerator = getSecureRandom();
+    }
+
+    /** 姝UID鐨勬渶楂�64鏈夋晥浣� */
+    private final long mostSigBits;
+
+    /** 姝UID鐨勬渶浣�64鏈夋晥浣� */
+    private final long leastSigBits;
+
+    /**
+     * 绉佹湁鏋勯��
+     * 
+     * @param data 鏁版嵁
+     */
+    private UUID(byte[] data)
+    {
+        long msb = 0;
+        long lsb = 0;
+        assert data.length == 16 : "data must be 16 bytes in length";
+        for (int i = 0; i < 8; i++)
+        {
+            msb = (msb << 8) | (data[i] & 0xff);
+        }
+        for (int i = 8; i < 16; i++)
+        {
+            lsb = (lsb << 8) | (data[i] & 0xff);
+        }
+        this.mostSigBits = msb;
+        this.leastSigBits = lsb;
+    }
+
+    /**
+     * 浣跨敤鎸囧畾鐨勬暟鎹瀯閫犳柊鐨� UUID銆�
+     *
+     * @param mostSigBits 鐢ㄤ簬 {@code UUID} 鐨勬渶楂樻湁鏁� 64 浣�
+     * @param leastSigBits 鐢ㄤ簬 {@code UUID} 鐨勬渶浣庢湁鏁� 64 浣�
+     */
+    public UUID(long mostSigBits, long leastSigBits)
+    {
+        this.mostSigBits = mostSigBits;
+        this.leastSigBits = leastSigBits;
+    }
+
+    /**
+     * 鑾峰彇绫诲瀷 4锛堜吉闅忔満鐢熸垚鐨勶級UUID 鐨勯潤鎬佸伐鍘傘��
+     * 
+     * @return 闅忔満鐢熸垚鐨� {@code UUID}
+     */
+    public static UUID fastUUID()
+    {
+        return randomUUID(false);
+    }
+
+    /**
+     * 鑾峰彇绫诲瀷 4锛堜吉闅忔満鐢熸垚鐨勶級UUID 鐨勯潤鎬佸伐鍘傘�� 浣跨敤鍔犲瘑鐨勫己浼殢鏈烘暟鐢熸垚鍣ㄧ敓鎴愯 UUID銆�
+     * 
+     * @return 闅忔満鐢熸垚鐨� {@code UUID}
+     */
+    public static UUID randomUUID()
+    {
+        return randomUUID(true);
+    }
+
+    /**
+     * 鑾峰彇绫诲瀷 4锛堜吉闅忔満鐢熸垚鐨勶級UUID 鐨勯潤鎬佸伐鍘傘�� 浣跨敤鍔犲瘑鐨勫己浼殢鏈烘暟鐢熸垚鍣ㄧ敓鎴愯 UUID銆�
+     * 
+     * @param isSecure 鏄惁浣跨敤{@link SecureRandom}濡傛灉鏄彲浠ヨ幏寰楁洿瀹夊叏鐨勯殢鏈虹爜锛屽惁鍒欏彲浠ュ緱鍒版洿濂界殑鎬ц兘
+     * @return 闅忔満鐢熸垚鐨� {@code UUID}
+     */
+    public static UUID randomUUID(boolean isSecure)
+    {
+        final Random ng = isSecure ? Holder.numberGenerator : getRandom();
+
+        byte[] randomBytes = new byte[16];
+        ng.nextBytes(randomBytes);
+        randomBytes[6] &= 0x0f; /* clear version */
+        randomBytes[6] |= 0x40; /* set to version 4 */
+        randomBytes[8] &= 0x3f; /* clear variant */
+        randomBytes[8] |= 0x80; /* set to IETF variant */
+        return new UUID(randomBytes);
+    }
+
+    /**
+     * 鏍规嵁鎸囧畾鐨勫瓧鑺傛暟缁勮幏鍙栫被鍨� 3锛堝熀浜庡悕绉扮殑锛塙UID 鐨勯潤鎬佸伐鍘傘��
+     *
+     * @param name 鐢ㄤ簬鏋勯�� UUID 鐨勫瓧鑺傛暟缁勩��
+     *
+     * @return 鏍规嵁鎸囧畾鏁扮粍鐢熸垚鐨� {@code UUID}
+     */
+    public static UUID nameUUIDFromBytes(byte[] name)
+    {
+        MessageDigest md;
+        try
+        {
+            md = MessageDigest.getInstance("MD5");
+        }
+        catch (NoSuchAlgorithmException nsae)
+        {
+            throw new InternalError("MD5 not supported");
+        }
+        byte[] md5Bytes = md.digest(name);
+        md5Bytes[6] &= 0x0f; /* clear version */
+        md5Bytes[6] |= 0x30; /* set to version 3 */
+        md5Bytes[8] &= 0x3f; /* clear variant */
+        md5Bytes[8] |= 0x80; /* set to IETF variant */
+        return new UUID(md5Bytes);
+    }
+
+    /**
+     * 鏍规嵁 {@link #toString()} 鏂规硶涓弿杩扮殑瀛楃涓叉爣鍑嗚〃绀哄舰寮忓垱寤簕@code UUID}銆�
+     *
+     * @param name 鎸囧畾 {@code UUID} 瀛楃涓�
+     * @return 鍏锋湁鎸囧畾鍊肩殑 {@code UUID}
+     * @throws IllegalArgumentException 濡傛灉 name 涓� {@link #toString} 涓弿杩扮殑瀛楃涓茶〃绀哄舰寮忎笉绗︽姏鍑烘寮傚父
+     *
+     */
+    public static UUID fromString(String name)
+    {
+        String[] components = name.split("-");
+        if (components.length != 5)
+        {
+            throw new IllegalArgumentException("Invalid UUID string: " + name);
+        }
+        for (int i = 0; i < 5; i++)
+        {
+            components[i] = "0x" + components[i];
+        }
+
+        long mostSigBits = Long.decode(components[0]).longValue();
+        mostSigBits <<= 16;
+        mostSigBits |= Long.decode(components[1]).longValue();
+        mostSigBits <<= 16;
+        mostSigBits |= Long.decode(components[2]).longValue();
+
+        long leastSigBits = Long.decode(components[3]).longValue();
+        leastSigBits <<= 48;
+        leastSigBits |= Long.decode(components[4]).longValue();
+
+        return new UUID(mostSigBits, leastSigBits);
+    }
+
+    /**
+     * 杩斿洖姝� UUID 鐨� 128 浣嶅�间腑鐨勬渶浣庢湁鏁� 64 浣嶃��
+     *
+     * @return 姝� UUID 鐨� 128 浣嶅�间腑鐨勬渶浣庢湁鏁� 64 浣嶃��
+     */
+    public long getLeastSignificantBits()
+    {
+        return leastSigBits;
+    }
+
+    /**
+     * 杩斿洖姝� UUID 鐨� 128 浣嶅�间腑鐨勬渶楂樻湁鏁� 64 浣嶃��
+     *
+     * @return 姝� UUID 鐨� 128 浣嶅�间腑鏈�楂樻湁鏁� 64 浣嶃��
+     */
+    public long getMostSignificantBits()
+    {
+        return mostSigBits;
+    }
+
+    /**
+     * 涓庢 {@code UUID} 鐩稿叧鑱旂殑鐗堟湰鍙�. 鐗堟湰鍙锋弿杩版 {@code UUID} 鏄浣曠敓鎴愮殑銆�
+     * <p>
+     * 鐗堟湰鍙峰叿鏈変互涓嬪惈鎰�:
+     * <ul>
+     * <li>1 鍩轰簬鏃堕棿鐨� UUID
+     * <li>2 DCE 瀹夊叏 UUID
+     * <li>3 鍩轰簬鍚嶇О鐨� UUID
+     * <li>4 闅忔満鐢熸垚鐨� UUID
+     * </ul>
+     *
+     * @return 姝� {@code UUID} 鐨勭増鏈彿
+     */
+    public int version()
+    {
+        // Version is bits masked by 0x000000000000F000 in MS long
+        return (int) ((mostSigBits >> 12) & 0x0f);
+    }
+
+    /**
+     * 涓庢 {@code UUID} 鐩稿叧鑱旂殑鍙樹綋鍙枫�傚彉浣撳彿鎻忚堪 {@code UUID} 鐨勫竷灞�銆�
+     * <p>
+     * 鍙樹綋鍙峰叿鏈変互涓嬪惈鎰忥細
+     * <ul>
+     * <li>0 涓� NCS 鍚戝悗鍏煎淇濈暀
+     * <li>2 <a href="http://www.ietf.org/rfc/rfc4122.txt">IETF&nbsp;RFC&nbsp;4122</a>(Leach-Salz), 鐢ㄤ簬姝ょ被
+     * <li>6 淇濈暀锛屽井杞悜鍚庡吋瀹�
+     * <li>7 淇濈暀渚涗互鍚庡畾涔変娇鐢�
+     * </ul>
+     *
+     * @return 姝� {@code UUID} 鐩稿叧鑱旂殑鍙樹綋鍙�
+     */
+    public int variant()
+    {
+        // This field is composed of a varying number of bits.
+        // 0 - - Reserved for NCS backward compatibility
+        // 1 0 - The IETF aka Leach-Salz variant (used by this class)
+        // 1 1 0 Reserved, Microsoft backward compatibility
+        // 1 1 1 Reserved for future definition.
+        return (int) ((leastSigBits >>> (64 - (leastSigBits >>> 62))) & (leastSigBits >> 63));
+    }
+
+    /**
+     * 涓庢 UUID 鐩稿叧鑱旂殑鏃堕棿鎴冲�笺��
+     *
+     * <p>
+     * 60 浣嶇殑鏃堕棿鎴冲�兼牴鎹 {@code UUID} 鐨� time_low銆乼ime_mid 鍜� time_hi 瀛楁鏋勯�犮��<br>
+     * 鎵�寰楀埌鐨勬椂闂存埑浠� 100 姣井绉掍负鍗曚綅锛屼粠 UTC锛堥�氱敤鍗忚皟鏃堕棿锛� 1582 骞� 10 鏈� 15 鏃ラ浂鏃跺紑濮嬨��
+     *
+     * <p>
+     * 鏃堕棿鎴冲�间粎鍦ㄥ湪鍩轰簬鏃堕棿鐨� UUID锛堝叾 version 绫诲瀷涓� 1锛変腑鎵嶆湁鎰忎箟銆�<br>
+     * 濡傛灉姝� {@code UUID} 涓嶆槸鍩轰簬鏃堕棿鐨� UUID锛屽垯姝ゆ柟娉曟姏鍑� UnsupportedOperationException銆�
+     *
+     * @throws UnsupportedOperationException 濡傛灉姝� {@code UUID} 涓嶆槸 version 涓� 1 鐨� UUID銆�
+     */
+    public long timestamp() throws UnsupportedOperationException
+    {
+        checkTimeBase();
+        return (mostSigBits & 0x0FFFL) << 48//
+                | ((mostSigBits >> 16) & 0x0FFFFL) << 32//
+                | mostSigBits >>> 32;
+    }
+
+    /**
+     * 涓庢 UUID 鐩稿叧鑱旂殑鏃堕挓搴忓垪鍊笺��
+     *
+     * <p>
+     * 14 浣嶇殑鏃堕挓搴忓垪鍊兼牴鎹 UUID 鐨� clock_seq 瀛楁鏋勯�犮�俢lock_seq 瀛楁鐢ㄤ簬淇濊瘉鍦ㄥ熀浜庢椂闂寸殑 UUID 涓殑鏃堕棿鍞竴鎬с��
+     * <p>
+     * {@code clockSequence} 鍊间粎鍦ㄥ熀浜庢椂闂寸殑 UUID锛堝叾 version 绫诲瀷涓� 1锛変腑鎵嶆湁鎰忎箟銆� 濡傛灉姝� UUID 涓嶆槸鍩轰簬鏃堕棿鐨� UUID锛屽垯姝ゆ柟娉曟姏鍑�
+     * UnsupportedOperationException銆�
+     *
+     * @return 姝� {@code UUID} 鐨勬椂閽熷簭鍒�
+     *
+     * @throws UnsupportedOperationException 濡傛灉姝� UUID 鐨� version 涓嶄负 1
+     */
+    public int clockSequence() throws UnsupportedOperationException
+    {
+        checkTimeBase();
+        return (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48);
+    }
+
+    /**
+     * 涓庢 UUID 鐩稿叧鐨勮妭鐐瑰�笺��
+     *
+     * <p>
+     * 48 浣嶇殑鑺傜偣鍊兼牴鎹 UUID 鐨� node 瀛楁鏋勯�犮�傛瀛楁鏃ㄥ湪鐢ㄤ簬淇濆瓨鏈哄櫒鐨� IEEE 802 鍦板潃锛岃鍦板潃鐢ㄤ簬鐢熸垚姝� UUID 浠ヤ繚璇佺┖闂村敮涓�鎬с��
+     * <p>
+     * 鑺傜偣鍊间粎鍦ㄥ熀浜庢椂闂寸殑 UUID锛堝叾 version 绫诲瀷涓� 1锛変腑鎵嶆湁鎰忎箟銆�<br>
+     * 濡傛灉姝� UUID 涓嶆槸鍩轰簬鏃堕棿鐨� UUID锛屽垯姝ゆ柟娉曟姏鍑� UnsupportedOperationException銆�
+     *
+     * @return 姝� {@code UUID} 鐨勮妭鐐瑰��
+     *
+     * @throws UnsupportedOperationException 濡傛灉姝� UUID 鐨� version 涓嶄负 1
+     */
+    public long node() throws UnsupportedOperationException
+    {
+        checkTimeBase();
+        return leastSigBits & 0x0000FFFFFFFFFFFFL;
+    }
+
+    /**
+     * 杩斿洖姝@code UUID} 鐨勫瓧绗︿覆琛ㄧ幇褰㈠紡銆�
+     *
+     * <p>
+     * UUID 鐨勫瓧绗︿覆琛ㄧず褰㈠紡鐢辨 BNF 鎻忚堪锛�
+     * 
+     * <pre>
+     * {@code
+     * UUID                   = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>
+     * time_low               = 4*<hexOctet>
+     * time_mid               = 2*<hexOctet>
+     * time_high_and_version  = 2*<hexOctet>
+     * variant_and_sequence   = 2*<hexOctet>
+     * node                   = 6*<hexOctet>
+     * hexOctet               = <hexDigit><hexDigit>
+     * hexDigit               = [0-9a-fA-F]
+     * }
+     * </pre>
+     * 
+     * </blockquote>
+     *
+     * @return 姝@code UUID} 鐨勫瓧绗︿覆琛ㄧ幇褰㈠紡
+     * @see #toString(boolean)
+     */
+    @Override
+    public String toString()
+    {
+        return toString(false);
+    }
+
+    /**
+     * 杩斿洖姝@code UUID} 鐨勫瓧绗︿覆琛ㄧ幇褰㈠紡銆�
+     *
+     * <p>
+     * UUID 鐨勫瓧绗︿覆琛ㄧず褰㈠紡鐢辨 BNF 鎻忚堪锛�
+     * 
+     * <pre>
+     * {@code
+     * UUID                   = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>
+     * time_low               = 4*<hexOctet>
+     * time_mid               = 2*<hexOctet>
+     * time_high_and_version  = 2*<hexOctet>
+     * variant_and_sequence   = 2*<hexOctet>
+     * node                   = 6*<hexOctet>
+     * hexOctet               = <hexDigit><hexDigit>
+     * hexDigit               = [0-9a-fA-F]
+     * }
+     * </pre>
+     * 
+     * </blockquote>
+     *
+     * @param isSimple 鏄惁绠�鍗曟ā寮忥紝绠�鍗曟ā寮忎负涓嶅甫'-'鐨刄UID瀛楃涓�
+     * @return 姝@code UUID} 鐨勫瓧绗︿覆琛ㄧ幇褰㈠紡
+     */
+    public String toString(boolean isSimple)
+    {
+        final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36);
+        // time_low
+        builder.append(digits(mostSigBits >> 32, 8));
+        if (!isSimple)
+        {
+            builder.append('-');
+        }
+        // time_mid
+        builder.append(digits(mostSigBits >> 16, 4));
+        if (!isSimple)
+        {
+            builder.append('-');
+        }
+        // time_high_and_version
+        builder.append(digits(mostSigBits, 4));
+        if (!isSimple)
+        {
+            builder.append('-');
+        }
+        // variant_and_sequence
+        builder.append(digits(leastSigBits >> 48, 4));
+        if (!isSimple)
+        {
+            builder.append('-');
+        }
+        // node
+        builder.append(digits(leastSigBits, 12));
+
+        return builder.toString();
+    }
+
+    /**
+     * 杩斿洖姝� UUID 鐨勫搱甯岀爜銆�
+     *
+     * @return UUID 鐨勫搱甯岀爜鍊笺��
+     */
+    @Override
+    public int hashCode()
+    {
+        long hilo = mostSigBits ^ leastSigBits;
+        return ((int) (hilo >> 32)) ^ (int) hilo;
+    }
+
+    /**
+     * 灏嗘瀵硅薄涓庢寚瀹氬璞℃瘮杈冦��
+     * <p>
+     * 褰撲笖浠呭綋鍙傛暟涓嶄负 {@code null}銆佽�屾槸涓�涓� UUID 瀵硅薄銆佸叿鏈変笌姝� UUID 鐩稿悓鐨� varriant銆佸寘鍚浉鍚岀殑鍊硷紙姣忎竴浣嶅潎鐩稿悓锛夋椂锛岀粨鏋滄墠涓� {@code true}銆�
+     *
+     * @param obj 瑕佷笌涔嬫瘮杈冪殑瀵硅薄
+     *
+     * @return 濡傛灉瀵硅薄鐩稿悓锛屽垯杩斿洖 {@code true}锛涘惁鍒欒繑鍥� {@code false}
+     */
+    @Override
+    public boolean equals(Object obj)
+    {
+        if ((null == obj) || (obj.getClass() != UUID.class))
+        {
+            return false;
+        }
+        UUID id = (UUID) obj;
+        return (mostSigBits == id.mostSigBits && leastSigBits == id.leastSigBits);
+    }
+
+    // Comparison Operations
+
+    /**
+     * 灏嗘 UUID 涓庢寚瀹氱殑 UUID 姣旇緝銆�
+     *
+     * <p>
+     * 濡傛灉涓や釜 UUID 涓嶅悓锛屼笖绗竴涓� UUID 鐨勬渶楂樻湁鏁堝瓧娈靛ぇ浜庣浜屼釜 UUID 鐨勫搴斿瓧娈碉紝鍒欑涓�涓� UUID 澶т簬绗簩涓� UUID銆�
+     *
+     * @param val 涓庢 UUID 姣旇緝鐨� UUID
+     *
+     * @return 鍦ㄦ UUID 灏忎簬銆佺瓑浜庢垨澶т簬 val 鏃讹紝鍒嗗埆杩斿洖 -1銆�0 鎴� 1銆�
+     *
+     */
+    @Override
+    public int compareTo(UUID val)
+    {
+        // The ordering is intentionally set up so that the UUIDs
+        // can simply be numerically compared as two numbers
+        return (this.mostSigBits < val.mostSigBits ? -1 : //
+                (this.mostSigBits > val.mostSigBits ? 1 : //
+                        (this.leastSigBits < val.leastSigBits ? -1 : //
+                                (this.leastSigBits > val.leastSigBits ? 1 : //
+                                        0))));
+    }
+
+    // -------------------------------------------------------------------------------------------------------------------
+    // Private method start
+    /**
+     * 杩斿洖鎸囧畾鏁板瓧瀵瑰簲鐨刪ex鍊�
+     * 
+     * @param val 鍊�
+     * @param digits 浣�
+     * @return 鍊�
+     */
+    private static String digits(long val, int digits)
+    {
+        long hi = 1L << (digits * 4);
+        return Long.toHexString(hi | (val & (hi - 1))).substring(1);
+    }
+
+    /**
+     * 妫�鏌ユ槸鍚︿负time-based鐗堟湰UUID
+     */
+    private void checkTimeBase()
+    {
+        if (version() != 1)
+        {
+            throw new UnsupportedOperationException("Not a time-based UUID");
+        }
+    }
+
+    /**
+     * 鑾峰彇{@link SecureRandom}锛岀被鎻愪緵鍔犲瘑鐨勫己闅忔満鏁扮敓鎴愬櫒 (RNG)
+     * 
+     * @return {@link SecureRandom}
+     */
+    public static SecureRandom getSecureRandom()
+    {
+        try
+        {
+            return SecureRandom.getInstance("SHA1PRNG");
+        }
+        catch (NoSuchAlgorithmException e)
+        {
+            throw new UtilException(e);
+        }
+    }
+
+    /**
+     * 鑾峰彇闅忔満鏁扮敓鎴愬櫒瀵硅薄<br>
+     * ThreadLocalRandom鏄疛DK 7涔嬪悗鎻愪緵骞跺彂浜х敓闅忔満鏁帮紝鑳藉瑙e喅澶氫釜绾跨▼鍙戠敓鐨勭珵浜変簤澶恒��
+     * 
+     * @return {@link ThreadLocalRandom}
+     */
+    public static ThreadLocalRandom getRandom()
+    {
+        return ThreadLocalRandom.current();
+    }
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/xss/Xss.java b/jcdm-common/src/main/java/com/jcdm/common/xss/Xss.java
new file mode 100644
index 0000000..f94e253
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/xss/Xss.java
@@ -0,0 +1,27 @@
+package com.jcdm.common.xss;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 鑷畾涔墄ss鏍¢獙娉ㄨВ
+ * 
+ * @author jc
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(value = { ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.PARAMETER })
+@Constraint(validatedBy = { XssValidator.class })
+public @interface Xss
+{
+    String message()
+
+    default "涓嶅厑璁镐换浣曡剼鏈繍琛�";
+
+    Class<?>[] groups() default {};
+
+    Class<? extends Payload>[] payload() default {};
+}
diff --git a/jcdm-common/src/main/java/com/jcdm/common/xss/XssValidator.java b/jcdm-common/src/main/java/com/jcdm/common/xss/XssValidator.java
new file mode 100644
index 0000000..5607fd1
--- /dev/null
+++ b/jcdm-common/src/main/java/com/jcdm/common/xss/XssValidator.java
@@ -0,0 +1,34 @@
+package com.jcdm.common.xss;
+
+import com.jcdm.common.utils.StringUtils;
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * 鑷畾涔墄ss鏍¢獙娉ㄨВ瀹炵幇
+ * 
+ * @author jc
+ */
+public class XssValidator implements ConstraintValidator<Xss, String>
+{
+    private static final String HTML_PATTERN = "<(\\S*?)[^>]*>.*?|<.*? />";
+
+    @Override
+    public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext)
+    {
+        if (StringUtils.isBlank(value))
+        {
+            return true;
+        }
+        return !containsHtml(value);
+    }
+
+    public static boolean containsHtml(String value)
+    {
+        Pattern pattern = Pattern.compile(HTML_PATTERN);
+        Matcher matcher = pattern.matcher(value);
+        return matcher.matches();
+    }
+}
\ No newline at end of file
diff --git a/jcdm-framework/pom.xml b/jcdm-framework/pom.xml
new file mode 100644
index 0000000..396e795
--- /dev/null
+++ b/jcdm-framework/pom.xml
@@ -0,0 +1,70 @@
+<?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">
+    <parent>
+        <artifactId>jcdm</artifactId>
+        <groupId>com.jcdm</groupId>
+        <version>3.8.6</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>jcdm-framework</artifactId>
+
+    <description>
+        framework妗嗘灦鏍稿績
+    </description>
+
+    <dependencies>
+
+        <!-- SpringBoot Web瀹瑰櫒 -->
+         <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+
+        <!-- SpringBoot 鎷︽埅鍣� -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-aop</artifactId>
+        </dependency>
+
+        <!-- 闃块噷鏁版嵁搴撹繛鎺ユ睜 -->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid-spring-boot-starter</artifactId>
+        </dependency>
+
+        <!-- 楠岃瘉鐮� -->
+        <dependency>
+            <groupId>pro.fessional</groupId>
+            <artifactId>kaptcha</artifactId>
+            <exclusions>
+                <exclusion>
+                    <artifactId>servlet-api</artifactId>
+                    <groupId>javax.servlet</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <!-- 鑾峰彇绯荤粺淇℃伅 -->
+        <dependency>
+            <groupId>com.github.oshi</groupId>
+            <artifactId>oshi-core</artifactId>
+        </dependency>
+
+        <!-- 绯荤粺妯″潡-->
+        <dependency>
+            <groupId>com.jcdm</groupId>
+            <artifactId>jcdm-system</artifactId>
+        </dependency>
+
+        <!-- SpringBoot Websocket -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-websocket</artifactId>
+        </dependency>
+
+    </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/aspectj/DataScopeAspect.java b/jcdm-framework/src/main/java/com/jcdm/framework/aspectj/DataScopeAspect.java
new file mode 100644
index 0000000..0b58331
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/aspectj/DataScopeAspect.java
@@ -0,0 +1,174 @@
+package com.jcdm.framework.aspectj;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.springframework.stereotype.Component;
+import com.jcdm.common.annotation.DataScope;
+import com.jcdm.common.core.domain.BaseEntity;
+import com.jcdm.common.core.domain.entity.SysRole;
+import com.jcdm.common.core.domain.entity.SysUser;
+import com.jcdm.common.core.domain.model.LoginUser;
+import com.jcdm.common.core.text.Convert;
+import com.jcdm.common.utils.SecurityUtils;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.framework.security.context.PermissionContextHolder;
+
+/**
+ * 鏁版嵁杩囨护澶勭悊
+ *
+ * @author jc
+ */
+@Aspect
+@Component
+public class DataScopeAspect
+{
+    /**
+     * 鍏ㄩ儴鏁版嵁鏉冮檺
+     */
+    public static final String DATA_SCOPE_ALL = "1";
+
+    /**
+     * 鑷畾鏁版嵁鏉冮檺
+     */
+    public static final String DATA_SCOPE_CUSTOM = "2";
+
+    /**
+     * 閮ㄩ棬鏁版嵁鏉冮檺
+     */
+    public static final String DATA_SCOPE_DEPT = "3";
+
+    /**
+     * 閮ㄩ棬鍙婁互涓嬫暟鎹潈闄�
+     */
+    public static final String DATA_SCOPE_DEPT_AND_CHILD = "4";
+
+    /**
+     * 浠呮湰浜烘暟鎹潈闄�
+     */
+    public static final String DATA_SCOPE_SELF = "5";
+
+    /**
+     * 鏁版嵁鏉冮檺杩囨护鍏抽敭瀛�
+     */
+    public static final String DATA_SCOPE = "dataScope";
+
+    @Before("@annotation(controllerDataScope)")
+    public void doBefore(JoinPoint point, DataScope controllerDataScope) throws Throwable
+    {
+        clearDataScope(point);
+        handleDataScope(point, controllerDataScope);
+    }
+
+    protected void handleDataScope(final JoinPoint joinPoint, DataScope controllerDataScope)
+    {
+        // 鑾峰彇褰撳墠鐨勭敤鎴�
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        if (StringUtils.isNotNull(loginUser))
+        {
+            SysUser currentUser = loginUser.getUser();
+            // 濡傛灉鏄秴绾х鐞嗗憳锛屽垯涓嶈繃婊ゆ暟鎹�
+            if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin())
+            {
+                String permission = StringUtils.defaultIfEmpty(controllerDataScope.permission(), PermissionContextHolder.getContext());
+                dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(),
+                        controllerDataScope.userAlias(), permission);
+            }
+        }
+    }
+
+    /**
+     * 鏁版嵁鑼冨洿杩囨护
+     *
+     * @param joinPoint 鍒囩偣
+     * @param user 鐢ㄦ埛
+     * @param deptAlias 閮ㄩ棬鍒悕
+     * @param userAlias 鐢ㄦ埛鍒悕
+     * @param permission 鏉冮檺瀛楃
+     */
+    public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias, String permission)
+    {
+        StringBuilder sqlString = new StringBuilder();
+        List<String> conditions = new ArrayList<String>();
+
+        for (SysRole role : user.getRoles())
+        {
+            String dataScope = role.getDataScope();
+            if (!DATA_SCOPE_CUSTOM.equals(dataScope) && conditions.contains(dataScope))
+            {
+                continue;
+            }
+            if (StringUtils.isNotEmpty(permission) && StringUtils.isNotEmpty(role.getPermissions())
+                    && !StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
+            {
+                continue;
+            }
+            if (DATA_SCOPE_ALL.equals(dataScope))
+            {
+                sqlString = new StringBuilder();
+                conditions.add(dataScope);
+                break;
+            }
+            else if (DATA_SCOPE_CUSTOM.equals(dataScope))
+            {
+                sqlString.append(StringUtils.format(
+                        " OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias,
+                        role.getRoleId()));
+            }
+            else if (DATA_SCOPE_DEPT.equals(dataScope))
+            {
+                sqlString.append(StringUtils.format(" OR {}.dept_id = {} ", deptAlias, user.getDeptId()));
+            }
+            else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope))
+            {
+                sqlString.append(StringUtils.format(
+                        " OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )",
+                        deptAlias, user.getDeptId(), user.getDeptId()));
+            }
+            else if (DATA_SCOPE_SELF.equals(dataScope))
+            {
+                if (StringUtils.isNotBlank(userAlias))
+                {
+                    sqlString.append(StringUtils.format(" OR {}.user_id = {} ", userAlias, user.getUserId()));
+                }
+                else
+                {
+                    // 鏁版嵁鏉冮檺涓轰粎鏈汉涓旀病鏈塽serAlias鍒悕涓嶆煡璇换浣曟暟鎹�
+                    sqlString.append(StringUtils.format(" OR {}.dept_id = 0 ", deptAlias));
+                }
+            }
+            conditions.add(dataScope);
+        }
+
+        // 澶氳鑹叉儏鍐典笅锛屾墍鏈夎鑹查兘涓嶅寘鍚紶閫掕繃鏉ョ殑鏉冮檺瀛楃锛岃繖涓椂鍊檚qlString涔熶細涓虹┖锛屾墍浠ヨ闄愬埗涓�涓�,涓嶆煡璇换浣曟暟鎹�
+        if (StringUtils.isEmpty(conditions))
+        {
+            sqlString.append(StringUtils.format(" OR {}.dept_id = 0 ", deptAlias));
+        }
+
+        if (StringUtils.isNotBlank(sqlString.toString()))
+        {
+            Object params = joinPoint.getArgs()[0];
+            if (StringUtils.isNotNull(params) && params instanceof BaseEntity)
+            {
+                BaseEntity baseEntity = (BaseEntity) params;
+                baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")");
+            }
+        }
+    }
+
+    /**
+     * 鎷兼帴鏉冮檺sql鍓嶅厛娓呯┖params.dataScope鍙傛暟闃叉娉ㄥ叆
+     */
+    private void clearDataScope(final JoinPoint joinPoint)
+    {
+        Object params = joinPoint.getArgs()[0];
+        if (StringUtils.isNotNull(params) && params instanceof BaseEntity)
+        {
+            BaseEntity baseEntity = (BaseEntity) params;
+            baseEntity.getParams().put(DATA_SCOPE, "");
+        }
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/aspectj/DataSourceAspect.java b/jcdm-framework/src/main/java/com/jcdm/framework/aspectj/DataSourceAspect.java
new file mode 100644
index 0000000..b1930b6
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/aspectj/DataSourceAspect.java
@@ -0,0 +1,72 @@
+package com.jcdm.framework.aspectj;
+
+import java.util.Objects;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.annotation.AnnotationUtils;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+import com.jcdm.common.annotation.DataSource;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.framework.datasource.DynamicDataSourceContextHolder;
+
+/**
+ * 澶氭暟鎹簮澶勭悊
+ * 
+ * @author jc
+ */
+@Aspect
+@Order(1)
+@Component
+public class DataSourceAspect
+{
+    protected Logger logger = LoggerFactory.getLogger(getClass());
+
+    @Pointcut("@annotation(com.jcdm.common.annotation.DataSource)"
+            + "|| @within(com.jcdm.common.annotation.DataSource)")
+    public void dsPointCut()
+    {
+
+    }
+
+    @Around("dsPointCut()")
+    public Object around(ProceedingJoinPoint point) throws Throwable
+    {
+        DataSource dataSource = getDataSource(point);
+
+        if (StringUtils.isNotNull(dataSource))
+        {
+            DynamicDataSourceContextHolder.setDataSourceType(dataSource.value().name());
+        }
+
+        try
+        {
+            return point.proceed();
+        }
+        finally
+        {
+            // 閿�姣佹暟鎹簮 鍦ㄦ墽琛屾柟娉曚箣鍚�
+            DynamicDataSourceContextHolder.clearDataSourceType();
+        }
+    }
+
+    /**
+     * 鑾峰彇闇�瑕佸垏鎹㈢殑鏁版嵁婧�
+     */
+    public DataSource getDataSource(ProceedingJoinPoint point)
+    {
+        MethodSignature signature = (MethodSignature) point.getSignature();
+        DataSource dataSource = AnnotationUtils.findAnnotation(signature.getMethod(), DataSource.class);
+        if (Objects.nonNull(dataSource))
+        {
+            return dataSource;
+        }
+
+        return AnnotationUtils.findAnnotation(signature.getDeclaringType(), DataSource.class);
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/aspectj/LogAspect.java b/jcdm-framework/src/main/java/com/jcdm/framework/aspectj/LogAspect.java
new file mode 100644
index 0000000..87b2267
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/aspectj/LogAspect.java
@@ -0,0 +1,249 @@
+package com.jcdm.framework.aspectj;
+
+import java.util.Collection;
+import java.util.Map;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.lang3.ArrayUtils;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.AfterReturning;
+import org.aspectj.lang.annotation.AfterThrowing;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.NamedThreadLocal;
+import org.springframework.stereotype.Component;
+import org.springframework.validation.BindingResult;
+import org.springframework.web.multipart.MultipartFile;
+import com.alibaba.fastjson2.JSON;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.domain.model.LoginUser;
+import com.jcdm.common.enums.BusinessStatus;
+import com.jcdm.common.enums.HttpMethod;
+import com.jcdm.common.filter.PropertyPreExcludeFilter;
+import com.jcdm.common.utils.SecurityUtils;
+import com.jcdm.common.utils.ServletUtils;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.common.utils.ip.IpUtils;
+import com.jcdm.framework.manager.AsyncManager;
+import com.jcdm.framework.manager.factory.AsyncFactory;
+import com.jcdm.system.domain.SysOperLog;
+
+/**
+ * 鎿嶄綔鏃ュ織璁板綍澶勭悊
+ * 
+ * @author jc
+ */
+@Aspect
+@Component
+public class LogAspect
+{
+    private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
+
+    /** 鎺掗櫎鏁忔劅灞炴�у瓧娈� */
+    public static final String[] EXCLUDE_PROPERTIES = { "password", "oldPassword", "newPassword", "confirmPassword" };
+
+    /** 璁$畻鎿嶄綔娑堣�楁椂闂� */
+    private static final ThreadLocal<Long> TIME_THREADLOCAL = new NamedThreadLocal<Long>("Cost Time");
+
+    /**
+     * 澶勭悊璇锋眰鍓嶆墽琛�
+     */
+    @Before(value = "@annotation(controllerLog)")
+    public void boBefore(JoinPoint joinPoint, Log controllerLog)
+    {
+        TIME_THREADLOCAL.set(System.currentTimeMillis());
+    }
+
+    /**
+     * 澶勭悊瀹岃姹傚悗鎵ц
+     *
+     * @param joinPoint 鍒囩偣
+     */
+    @AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult")
+    public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult)
+    {
+        handleLog(joinPoint, controllerLog, null, jsonResult);
+    }
+
+    /**
+     * 鎷︽埅寮傚父鎿嶄綔
+     * 
+     * @param joinPoint 鍒囩偣
+     * @param e 寮傚父
+     */
+    @AfterThrowing(value = "@annotation(controllerLog)", throwing = "e")
+    public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e)
+    {
+        handleLog(joinPoint, controllerLog, e, null);
+    }
+
+    protected void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object jsonResult)
+    {
+        try
+        {
+            // 鑾峰彇褰撳墠鐨勭敤鎴�
+            LoginUser loginUser = SecurityUtils.getLoginUser();
+
+            // *========鏁版嵁搴撴棩蹇�=========*//
+            SysOperLog operLog = new SysOperLog();
+            operLog.setStatus(BusinessStatus.SUCCESS.ordinal());
+            // 璇锋眰鐨勫湴鍧�
+            String ip = IpUtils.getIpAddr();
+            operLog.setOperIp(ip);
+            operLog.setOperUrl(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255));
+            if (loginUser != null)
+            {
+                operLog.setOperName(loginUser.getUsername());
+            }
+
+            if (e != null)
+            {
+                operLog.setStatus(BusinessStatus.FAIL.ordinal());
+                operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));
+            }
+            // 璁剧疆鏂规硶鍚嶇О
+            String className = joinPoint.getTarget().getClass().getName();
+            String methodName = joinPoint.getSignature().getName();
+            operLog.setMethod(className + "." + methodName + "()");
+            // 璁剧疆璇锋眰鏂瑰紡
+            operLog.setRequestMethod(ServletUtils.getRequest().getMethod());
+            // 澶勭悊璁剧疆娉ㄨВ涓婄殑鍙傛暟
+            getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult);
+            // 璁剧疆娑堣�楁椂闂�
+            operLog.setCostTime(System.currentTimeMillis() - TIME_THREADLOCAL.get());
+            // 淇濆瓨鏁版嵁搴�
+            AsyncManager.me().execute(AsyncFactory.recordOper(operLog));
+        }
+        catch (Exception exp)
+        {
+            // 璁板綍鏈湴寮傚父鏃ュ織
+            log.error("寮傚父淇℃伅:{}", exp.getMessage());
+            exp.printStackTrace();
+        }
+        finally
+        {
+            TIME_THREADLOCAL.remove();
+        }
+    }
+
+    /**
+     * 鑾峰彇娉ㄨВ涓鏂规硶鐨勬弿杩颁俊鎭� 鐢ㄤ簬Controller灞傛敞瑙�
+     * 
+     * @param log 鏃ュ織
+     * @param operLog 鎿嶄綔鏃ュ織
+     * @throws Exception
+     */
+    public void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysOperLog operLog, Object jsonResult) throws Exception
+    {
+        // 璁剧疆action鍔ㄤ綔
+        operLog.setBusinessType(log.businessType().ordinal());
+        // 璁剧疆鏍囬
+        operLog.setTitle(log.title());
+        // 璁剧疆鎿嶄綔浜虹被鍒�
+        operLog.setOperatorType(log.operatorType().ordinal());
+        // 鏄惁闇�瑕佷繚瀛榬equest锛屽弬鏁板拰鍊�
+        if (log.isSaveRequestData())
+        {
+            // 鑾峰彇鍙傛暟鐨勪俊鎭紝浼犲叆鍒版暟鎹簱涓��
+            setRequestValue(joinPoint, operLog, log.excludeParamNames());
+        }
+        // 鏄惁闇�瑕佷繚瀛榬esponse锛屽弬鏁板拰鍊�
+        if (log.isSaveResponseData() && StringUtils.isNotNull(jsonResult))
+        {
+            operLog.setJsonResult(StringUtils.substring(JSON.toJSONString(jsonResult), 0, 2000));
+        }
+    }
+
+    /**
+     * 鑾峰彇璇锋眰鐨勫弬鏁帮紝鏀惧埌log涓�
+     * 
+     * @param operLog 鎿嶄綔鏃ュ織
+     * @throws Exception 寮傚父
+     */
+    private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog, String[] excludeParamNames) throws Exception
+    {
+        Map<?, ?> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest());
+        String requestMethod = operLog.getRequestMethod();
+        if (StringUtils.isEmpty(paramsMap)
+                && (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)))
+        {
+            String params = argsArrayToString(joinPoint.getArgs(), excludeParamNames);
+            operLog.setOperParam(StringUtils.substring(params, 0, 2000));
+        }
+        else
+        {
+            operLog.setOperParam(StringUtils.substring(JSON.toJSONString(paramsMap, excludePropertyPreFilter(excludeParamNames)), 0, 2000));
+        }
+    }
+
+    /**
+     * 鍙傛暟鎷艰
+     */
+    private String argsArrayToString(Object[] paramsArray, String[] excludeParamNames)
+    {
+        String params = "";
+        if (paramsArray != null && paramsArray.length > 0)
+        {
+            for (Object o : paramsArray)
+            {
+                if (StringUtils.isNotNull(o) && !isFilterObject(o))
+                {
+                    try
+                    {
+                        String jsonObj = JSON.toJSONString(o, excludePropertyPreFilter(excludeParamNames));
+                        params += jsonObj.toString() + " ";
+                    }
+                    catch (Exception e)
+                    {
+                    }
+                }
+            }
+        }
+        return params.trim();
+    }
+
+    /**
+     * 蹇界暐鏁忔劅灞炴��
+     */
+    public PropertyPreExcludeFilter excludePropertyPreFilter(String[] excludeParamNames)
+    {
+        return new PropertyPreExcludeFilter().addExcludes(ArrayUtils.addAll(EXCLUDE_PROPERTIES, excludeParamNames));
+    }
+
+    /**
+     * 鍒ゆ柇鏄惁闇�瑕佽繃婊ょ殑瀵硅薄銆�
+     * 
+     * @param o 瀵硅薄淇℃伅銆�
+     * @return 濡傛灉鏄渶瑕佽繃婊ょ殑瀵硅薄锛屽垯杩斿洖true锛涘惁鍒欒繑鍥瀎alse銆�
+     */
+    @SuppressWarnings("rawtypes")
+    public boolean isFilterObject(final Object o)
+    {
+        Class<?> clazz = o.getClass();
+        if (clazz.isArray())
+        {
+            return clazz.getComponentType().isAssignableFrom(MultipartFile.class);
+        }
+        else if (Collection.class.isAssignableFrom(clazz))
+        {
+            Collection collection = (Collection) o;
+            for (Object value : collection)
+            {
+                return value instanceof MultipartFile;
+            }
+        }
+        else if (Map.class.isAssignableFrom(clazz))
+        {
+            Map map = (Map) o;
+            for (Object value : map.entrySet())
+            {
+                Map.Entry entry = (Map.Entry) value;
+                return entry.getValue() instanceof MultipartFile;
+            }
+        }
+        return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse
+                || o instanceof BindingResult;
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/aspectj/RateLimiterAspect.java b/jcdm-framework/src/main/java/com/jcdm/framework/aspectj/RateLimiterAspect.java
new file mode 100644
index 0000000..6e7ac2e
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/aspectj/RateLimiterAspect.java
@@ -0,0 +1,89 @@
+package com.jcdm.framework.aspectj;
+
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.List;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.script.RedisScript;
+import org.springframework.stereotype.Component;
+import com.jcdm.common.annotation.RateLimiter;
+import com.jcdm.common.enums.LimitType;
+import com.jcdm.common.exception.ServiceException;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.common.utils.ip.IpUtils;
+
+/**
+ * 闄愭祦澶勭悊
+ *
+ * @author jc
+ */
+//@Aspect
+//@Component
+public class RateLimiterAspect
+{
+    private static final Logger log = LoggerFactory.getLogger(RateLimiterAspect.class);
+
+    private RedisTemplate<Object, Object> redisTemplate;
+
+    private RedisScript<Long> limitScript;
+
+//    @Autowired
+    public void setRedisTemplate1(RedisTemplate<Object, Object> redisTemplate)
+    {
+        this.redisTemplate = redisTemplate;
+    }
+
+//    @Autowired
+    public void setLimitScript(RedisScript<Long> limitScript)
+    {
+        this.limitScript = limitScript;
+    }
+
+    @Before("@annotation(rateLimiter)")
+    public void doBefore(JoinPoint point, RateLimiter rateLimiter) throws Throwable
+    {
+        int time = rateLimiter.time();
+        int count = rateLimiter.count();
+
+        String combineKey = getCombineKey(rateLimiter, point);
+        List<Object> keys = Collections.singletonList(combineKey);
+        try
+        {
+            Long number = redisTemplate.execute(limitScript, keys, count, time);
+            if (StringUtils.isNull(number) || number.intValue() > count)
+            {
+                throw new ServiceException("璁块棶杩囦簬棰戠箒锛岃绋嶅�欏啀璇�");
+            }
+            log.info("闄愬埗璇锋眰'{}',褰撳墠璇锋眰'{}',缂撳瓨key'{}'", count, number.intValue(), combineKey);
+        }
+        catch (ServiceException e)
+        {
+            throw e;
+        }
+        catch (Exception e)
+        {
+            throw new RuntimeException("鏈嶅姟鍣ㄩ檺娴佸紓甯革紝璇风◢鍊欏啀璇�");
+        }
+    }
+
+    public String getCombineKey(RateLimiter rateLimiter, JoinPoint point)
+    {
+        StringBuffer stringBuffer = new StringBuffer(rateLimiter.key());
+        if (rateLimiter.limitType() == LimitType.IP)
+        {
+            stringBuffer.append(IpUtils.getIpAddr()).append("-");
+        }
+        MethodSignature signature = (MethodSignature) point.getSignature();
+        Method method = signature.getMethod();
+        Class<?> targetClass = method.getDeclaringClass();
+        stringBuffer.append(targetClass.getName()).append("-").append(method.getName());
+        return stringBuffer.toString();
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/config/ApplicationConfig.java b/jcdm-framework/src/main/java/com/jcdm/framework/config/ApplicationConfig.java
new file mode 100644
index 0000000..91160e3
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/config/ApplicationConfig.java
@@ -0,0 +1,30 @@
+package com.jcdm.framework.config;
+
+import java.util.TimeZone;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+
+/**
+ * 绋嬪簭娉ㄨВ閰嶇疆
+ *
+ * @author jc
+ */
+@Configuration
+// 琛ㄧず閫氳繃aop妗嗘灦鏆撮湶璇ヤ唬鐞嗗璞�,AopContext鑳藉璁块棶
+@EnableAspectJAutoProxy(exposeProxy = true)
+// 鎸囧畾瑕佹壂鎻忕殑Mapper绫荤殑鍖呯殑璺緞
+@MapperScan("com.jcdm.**.mapper")
+public class ApplicationConfig
+{
+    /**
+     * 鏃跺尯閰嶇疆
+     */
+    @Bean
+    public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization()
+    {
+        return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.timeZone(TimeZone.getDefault());
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/config/CaptchaConfig.java b/jcdm-framework/src/main/java/com/jcdm/framework/config/CaptchaConfig.java
new file mode 100644
index 0000000..0ff5da9
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/config/CaptchaConfig.java
@@ -0,0 +1,83 @@
+package com.jcdm.framework.config;
+
+import java.util.Properties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import com.google.code.kaptcha.impl.DefaultKaptcha;
+import com.google.code.kaptcha.util.Config;
+import static com.google.code.kaptcha.Constants.*;
+
+/**
+ * 楠岃瘉鐮侀厤缃�
+ * 
+ * @author jc
+ */
+@Configuration
+public class CaptchaConfig
+{
+    @Bean(name = "captchaProducer")
+    public DefaultKaptcha getKaptchaBean()
+    {
+        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
+        Properties properties = new Properties();
+        // 鏄惁鏈夎竟妗� 榛樿涓簍rue 鎴戜滑鍙互鑷繁璁剧疆yes锛宯o
+        properties.setProperty(KAPTCHA_BORDER, "yes");
+        // 楠岃瘉鐮佹枃鏈瓧绗﹂鑹� 榛樿涓篊olor.BLACK
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black");
+        // 楠岃瘉鐮佸浘鐗囧搴� 榛樿涓�200
+        properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
+        // 楠岃瘉鐮佸浘鐗囬珮搴� 榛樿涓�50
+        properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
+        // 楠岃瘉鐮佹枃鏈瓧绗﹀ぇ灏� 榛樿涓�40
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38");
+        // KAPTCHA_SESSION_KEY
+        properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode");
+        // 楠岃瘉鐮佹枃鏈瓧绗﹂暱搴� 榛樿涓�5
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4");
+        // 楠岃瘉鐮佹枃鏈瓧浣撴牱寮� 榛樿涓簄ew Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
+        // 鍥剧墖鏍峰紡 姘寸汗com.google.code.kaptcha.impl.WaterRipple 楸肩溂com.google.code.kaptcha.impl.FishEyeGimpy 闃村奖com.google.code.kaptcha.impl.ShadowGimpy
+        properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
+        Config config = new Config(properties);
+        defaultKaptcha.setConfig(config);
+        return defaultKaptcha;
+    }
+
+    @Bean(name = "captchaProducerMath")
+    public DefaultKaptcha getKaptchaBeanMath()
+    {
+        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
+        Properties properties = new Properties();
+        // 鏄惁鏈夎竟妗� 榛樿涓簍rue 鎴戜滑鍙互鑷繁璁剧疆yes锛宯o
+        properties.setProperty(KAPTCHA_BORDER, "yes");
+        // 杈规棰滆壊 榛樿涓篊olor.BLACK
+        properties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90");
+        // 楠岃瘉鐮佹枃鏈瓧绗﹂鑹� 榛樿涓篊olor.BLACK
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue");
+        // 楠岃瘉鐮佸浘鐗囧搴� 榛樿涓�200
+        properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
+        // 楠岃瘉鐮佸浘鐗囬珮搴� 榛樿涓�50
+        properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
+        // 楠岃瘉鐮佹枃鏈瓧绗﹀ぇ灏� 榛樿涓�40
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "35");
+        // KAPTCHA_SESSION_KEY
+        properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath");
+        // 楠岃瘉鐮佹枃鏈敓鎴愬櫒
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.jcdm.framework.config.KaptchaTextCreator");
+        // 楠岃瘉鐮佹枃鏈瓧绗﹂棿璺� 榛樿涓�2
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3");
+        // 楠岃瘉鐮佹枃鏈瓧绗﹂暱搴� 榛樿涓�5
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "6");
+        // 楠岃瘉鐮佹枃鏈瓧浣撴牱寮� 榛樿涓簄ew Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
+        // 楠岃瘉鐮佸櫔鐐归鑹� 榛樿涓篊olor.BLACK
+        properties.setProperty(KAPTCHA_NOISE_COLOR, "white");
+        // 骞叉壈瀹炵幇绫�
+        properties.setProperty(KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise");
+        // 鍥剧墖鏍峰紡 姘寸汗com.google.code.kaptcha.impl.WaterRipple 楸肩溂com.google.code.kaptcha.impl.FishEyeGimpy 闃村奖com.google.code.kaptcha.impl.ShadowGimpy
+        properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
+        Config config = new Config(properties);
+        defaultKaptcha.setConfig(config);
+        return defaultKaptcha;
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/config/DruidConfig.java b/jcdm-framework/src/main/java/com/jcdm/framework/config/DruidConfig.java
new file mode 100644
index 0000000..cddd539
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/config/DruidConfig.java
@@ -0,0 +1,126 @@
+package com.jcdm.framework.config;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.sql.DataSource;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import com.alibaba.druid.pool.DruidDataSource;
+import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
+import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
+import com.alibaba.druid.util.Utils;
+import com.jcdm.common.enums.DataSourceType;
+import com.jcdm.common.utils.spring.SpringUtils;
+import com.jcdm.framework.config.properties.DruidProperties;
+import com.jcdm.framework.datasource.DynamicDataSource;
+
+/**
+ * druid 閰嶇疆澶氭暟鎹簮
+ * 
+ * @author jc
+ */
+@Configuration
+public class DruidConfig
+{
+    @Bean
+    @ConfigurationProperties("spring.datasource.druid.master")
+    public DataSource masterDataSource(DruidProperties druidProperties)
+    {
+        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
+        return druidProperties.dataSource(dataSource);
+    }
+
+    @Bean
+    @ConfigurationProperties("spring.datasource.druid.slave")
+    @ConditionalOnProperty(prefix = "spring.datasource.druid.slave", name = "enabled", havingValue = "true")
+    public DataSource slaveDataSource(DruidProperties druidProperties)
+    {
+        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
+        return druidProperties.dataSource(dataSource);
+    }
+
+    @Bean(name = "dynamicDataSource")
+    @Primary
+    public DynamicDataSource dataSource(DataSource masterDataSource)
+    {
+        Map<Object, Object> targetDataSources = new HashMap<>();
+        targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource);
+        setDataSource(targetDataSources, DataSourceType.SLAVE.name(), "slaveDataSource");
+        return new DynamicDataSource(masterDataSource, targetDataSources);
+    }
+    
+    /**
+     * 璁剧疆鏁版嵁婧�
+     * 
+     * @param targetDataSources 澶囬�夋暟鎹簮闆嗗悎
+     * @param sourceName 鏁版嵁婧愬悕绉�
+     * @param beanName bean鍚嶇О
+     */
+    public void setDataSource(Map<Object, Object> targetDataSources, String sourceName, String beanName)
+    {
+        try
+        {
+            DataSource dataSource = SpringUtils.getBean(beanName);
+            targetDataSources.put(sourceName, dataSource);
+        }
+        catch (Exception e)
+        {
+        }
+    }
+
+    /**
+     * 鍘婚櫎鐩戞帶椤甸潰搴曢儴鐨勫箍鍛�
+     */
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Bean
+    @ConditionalOnProperty(name = "spring.datasource.druid.statViewServlet.enabled", havingValue = "true")
+    public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties)
+    {
+        // 鑾峰彇web鐩戞帶椤甸潰鐨勫弬鏁�
+        DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();
+        // 鎻愬彇common.js鐨勯厤缃矾寰�
+        String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*";
+        String commonJsPattern = pattern.replaceAll("\\*", "js/common.js");
+        final String filePath = "support/http/resources/js/common.js";
+        // 鍒涘缓filter杩涜杩囨护
+        Filter filter = new Filter()
+        {
+            @Override
+            public void init(javax.servlet.FilterConfig filterConfig) throws ServletException
+            {
+            }
+            @Override
+            public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+                    throws IOException, ServletException
+            {
+                chain.doFilter(request, response);
+                // 閲嶇疆缂撳啿鍖猴紝鍝嶅簲澶翠笉浼氳閲嶇疆
+                response.resetBuffer();
+                // 鑾峰彇common.js
+                String text = Utils.readFromResource(filePath);
+                // 姝e垯鏇挎崲banner, 闄ゅ幓搴曢儴鐨勫箍鍛婁俊鎭�
+                text = text.replaceAll("<a.*?banner\"></a><br/>", "");
+                text = text.replaceAll("powered.*?shrek.wang</a>", "");
+                response.getWriter().write(text);
+            }
+            @Override
+            public void destroy()
+            {
+            }
+        };
+        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
+        registrationBean.setFilter(filter);
+        registrationBean.addUrlPatterns(commonJsPattern);
+        return registrationBean;
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/config/FastJson2JsonRedisSerializer.java b/jcdm-framework/src/main/java/com/jcdm/framework/config/FastJson2JsonRedisSerializer.java
new file mode 100644
index 0000000..77fd196
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/config/FastJson2JsonRedisSerializer.java
@@ -0,0 +1,52 @@
+package com.jcdm.framework.config;
+
+import java.nio.charset.Charset;
+import org.springframework.data.redis.serializer.RedisSerializer;
+import org.springframework.data.redis.serializer.SerializationException;
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONReader;
+import com.alibaba.fastjson2.JSONWriter;
+import com.alibaba.fastjson2.filter.Filter;
+import com.jcdm.common.constant.Constants;
+
+/**
+ * Redis浣跨敤FastJson搴忓垪鍖�
+ * 
+ * @author jc
+ */
+public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T>
+{
+    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
+
+    static final Filter AUTO_TYPE_FILTER = JSONReader.autoTypeFilter(Constants.JSON_WHITELIST_STR);
+
+    private Class<T> clazz;
+
+    public FastJson2JsonRedisSerializer(Class<T> clazz)
+    {
+        super();
+        this.clazz = clazz;
+    }
+
+    @Override
+    public byte[] serialize(T t) throws SerializationException
+    {
+        if (t == null)
+        {
+            return new byte[0];
+        }
+        return JSON.toJSONString(t, JSONWriter.Feature.WriteClassName).getBytes(DEFAULT_CHARSET);
+    }
+
+    @Override
+    public T deserialize(byte[] bytes) throws SerializationException
+    {
+        if (bytes == null || bytes.length <= 0)
+        {
+            return null;
+        }
+        String str = new String(bytes, DEFAULT_CHARSET);
+
+        return JSON.parseObject(str, clazz, AUTO_TYPE_FILTER);
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/config/FilterConfig.java b/jcdm-framework/src/main/java/com/jcdm/framework/config/FilterConfig.java
new file mode 100644
index 0000000..abf612b
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/config/FilterConfig.java
@@ -0,0 +1,58 @@
+package com.jcdm.framework.config;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.servlet.DispatcherType;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import com.jcdm.common.filter.RepeatableFilter;
+import com.jcdm.common.filter.XssFilter;
+import com.jcdm.common.utils.StringUtils;
+
+/**
+ * Filter閰嶇疆
+ *
+ * @author jc
+ */
+@Configuration
+public class FilterConfig
+{
+    @Value("${xss.excludes}")
+    private String excludes;
+
+    @Value("${xss.urlPatterns}")
+    private String urlPatterns;
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Bean
+    @ConditionalOnProperty(value = "xss.enabled", havingValue = "true")
+    public FilterRegistrationBean xssFilterRegistration()
+    {
+        FilterRegistrationBean registration = new FilterRegistrationBean();
+        registration.setDispatcherTypes(DispatcherType.REQUEST);
+        registration.setFilter(new XssFilter());
+        registration.addUrlPatterns(StringUtils.split(urlPatterns, ","));
+        registration.setName("xssFilter");
+        registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE);
+        Map<String, String> initParameters = new HashMap<String, String>();
+        initParameters.put("excludes", excludes);
+        registration.setInitParameters(initParameters);
+        return registration;
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Bean
+    public FilterRegistrationBean someFilterRegistration()
+    {
+        FilterRegistrationBean registration = new FilterRegistrationBean();
+        registration.setFilter(new RepeatableFilter());
+        registration.addUrlPatterns("/*");
+        registration.setName("repeatableFilter");
+        registration.setOrder(FilterRegistrationBean.LOWEST_PRECEDENCE);
+        return registration;
+    }
+
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/config/KaptchaTextCreator.java b/jcdm-framework/src/main/java/com/jcdm/framework/config/KaptchaTextCreator.java
new file mode 100644
index 0000000..10f5312
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/config/KaptchaTextCreator.java
@@ -0,0 +1,68 @@
+package com.jcdm.framework.config;
+
+import java.util.Random;
+import com.google.code.kaptcha.text.impl.DefaultTextCreator;
+
+/**
+ * 楠岃瘉鐮佹枃鏈敓鎴愬櫒
+ *
+ * @author jc
+ */
+public class KaptchaTextCreator extends DefaultTextCreator
+{
+    private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(",");
+
+    @Override
+    public String getText()
+    {
+        Integer result = 0;
+        Random random = new Random();
+        int x = random.nextInt(10);
+        int y = random.nextInt(10);
+        StringBuilder suChinese = new StringBuilder();
+        int randomoperands = random.nextInt(3);
+        if (randomoperands == 0)
+        {
+            result = x * y;
+            suChinese.append(CNUMBERS[x]);
+            suChinese.append("*");
+            suChinese.append(CNUMBERS[y]);
+        }
+        else if (randomoperands == 1)
+        {
+            if ((x != 0) && y % x == 0)
+            {
+                result = y / x;
+                suChinese.append(CNUMBERS[y]);
+                suChinese.append("/");
+                suChinese.append(CNUMBERS[x]);
+            }
+            else
+            {
+                result = x + y;
+                suChinese.append(CNUMBERS[x]);
+                suChinese.append("+");
+                suChinese.append(CNUMBERS[y]);
+            }
+        }
+        else
+        {
+            if (x >= y)
+            {
+                result = x - y;
+                suChinese.append(CNUMBERS[x]);
+                suChinese.append("-");
+                suChinese.append(CNUMBERS[y]);
+            }
+            else
+            {
+                result = y - x;
+                suChinese.append(CNUMBERS[y]);
+                suChinese.append("-");
+                suChinese.append(CNUMBERS[x]);
+            }
+        }
+        suChinese.append("=?@" + result);
+        return suChinese.toString();
+    }
+}
\ No newline at end of file
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/config/MyBatisConfig.java b/jcdm-framework/src/main/java/com/jcdm/framework/config/MyBatisConfig.java
new file mode 100644
index 0000000..d1c06d5
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/config/MyBatisConfig.java
@@ -0,0 +1,132 @@
+package com.jcdm.framework.config;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import javax.sql.DataSource;
+import org.apache.ibatis.io.VFS;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.mybatis.spring.SqlSessionFactoryBean;
+import org.mybatis.spring.boot.autoconfigure.SpringBootVFS;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
+import org.springframework.core.io.DefaultResourceLoader;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+import org.springframework.core.io.support.ResourcePatternResolver;
+import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
+import org.springframework.core.type.classreading.MetadataReader;
+import org.springframework.core.type.classreading.MetadataReaderFactory;
+import org.springframework.util.ClassUtils;
+import com.jcdm.common.utils.StringUtils;
+
+/**
+ * Mybatis鏀寔*鍖归厤鎵弿鍖�
+ * 
+ * @author jc
+ */
+@Configuration
+public class MyBatisConfig
+{
+    @Autowired
+    private Environment env;
+
+    static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";
+
+    public static String setTypeAliasesPackage(String typeAliasesPackage)
+    {
+        ResourcePatternResolver resolver = (ResourcePatternResolver) new PathMatchingResourcePatternResolver();
+        MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resolver);
+        List<String> allResult = new ArrayList<String>();
+        try
+        {
+            for (String aliasesPackage : typeAliasesPackage.split(","))
+            {
+                List<String> result = new ArrayList<String>();
+                aliasesPackage = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
+                        + ClassUtils.convertClassNameToResourcePath(aliasesPackage.trim()) + "/" + DEFAULT_RESOURCE_PATTERN;
+                Resource[] resources = resolver.getResources(aliasesPackage);
+                if (resources != null && resources.length > 0)
+                {
+                    MetadataReader metadataReader = null;
+                    for (Resource resource : resources)
+                    {
+                        if (resource.isReadable())
+                        {
+                            metadataReader = metadataReaderFactory.getMetadataReader(resource);
+                            try
+                            {
+                                result.add(Class.forName(metadataReader.getClassMetadata().getClassName()).getPackage().getName());
+                            }
+                            catch (ClassNotFoundException e)
+                            {
+                                e.printStackTrace();
+                            }
+                        }
+                    }
+                }
+                if (result.size() > 0)
+                {
+                    HashSet<String> hashResult = new HashSet<String>(result);
+                    allResult.addAll(hashResult);
+                }
+            }
+            if (allResult.size() > 0)
+            {
+                typeAliasesPackage = String.join(",", (String[]) allResult.toArray(new String[0]));
+            }
+            else
+            {
+                throw new RuntimeException("mybatis typeAliasesPackage 璺緞鎵弿閿欒,鍙傛暟typeAliasesPackage:" + typeAliasesPackage + "鏈壘鍒颁换浣曞寘");
+            }
+        }
+        catch (IOException e)
+        {
+            e.printStackTrace();
+        }
+        return typeAliasesPackage;
+    }
+
+    public Resource[] resolveMapperLocations(String[] mapperLocations)
+    {
+        ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
+        List<Resource> resources = new ArrayList<Resource>();
+        if (mapperLocations != null)
+        {
+            for (String mapperLocation : mapperLocations)
+            {
+                try
+                {
+                    Resource[] mappers = resourceResolver.getResources(mapperLocation);
+                    resources.addAll(Arrays.asList(mappers));
+                }
+                catch (IOException e)
+                {
+                    // ignore
+                }
+            }
+        }
+        return resources.toArray(new Resource[resources.size()]);
+    }
+
+    @Bean
+    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception
+    {
+        String typeAliasesPackage = env.getProperty("mybatis.typeAliasesPackage");
+        String mapperLocations = env.getProperty("mybatis.mapperLocations");
+        String configLocation = env.getProperty("mybatis.configLocation");
+        typeAliasesPackage = setTypeAliasesPackage(typeAliasesPackage);
+        VFS.addImplClass(SpringBootVFS.class);
+
+        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
+        sessionFactory.setDataSource(dataSource);
+        sessionFactory.setTypeAliasesPackage(typeAliasesPackage);
+        sessionFactory.setMapperLocations(resolveMapperLocations(StringUtils.split(mapperLocations, ",")));
+        sessionFactory.setConfigLocation(new DefaultResourceLoader().getResource(configLocation));
+        return sessionFactory.getObject();
+    }
+}
\ No newline at end of file
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/config/RedisConfig.java b/jcdm-framework/src/main/java/com/jcdm/framework/config/RedisConfig.java
new file mode 100644
index 0000000..86d39e8
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/config/RedisConfig.java
@@ -0,0 +1,69 @@
+package com.jcdm.framework.config;
+
+import org.springframework.cache.annotation.CachingConfigurerSupport;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.script.DefaultRedisScript;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+/**
+ * redis閰嶇疆
+ * 
+ * @author jc
+ */
+//@Configuration
+//@EnableCaching
+public class RedisConfig extends CachingConfigurerSupport
+{
+//    @Bean
+    @SuppressWarnings(value = { "unchecked", "rawtypes" })
+    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory)
+    {
+        RedisTemplate<Object, Object> template = new RedisTemplate<>();
+        template.setConnectionFactory(connectionFactory);
+
+        FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);
+
+        // 浣跨敤StringRedisSerializer鏉ュ簭鍒楀寲鍜屽弽搴忓垪鍖杛edis鐨刱ey鍊�
+        template.setKeySerializer(new StringRedisSerializer());
+        template.setValueSerializer(serializer);
+
+        // Hash鐨刱ey涔熼噰鐢⊿tringRedisSerializer鐨勫簭鍒楀寲鏂瑰紡
+        template.setHashKeySerializer(new StringRedisSerializer());
+        template.setHashValueSerializer(serializer);
+
+        template.afterPropertiesSet();
+        return template;
+    }
+
+//    @Bean
+    public DefaultRedisScript<Long> limitScript()
+    {
+        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
+        redisScript.setScriptText(limitScriptText());
+        redisScript.setResultType(Long.class);
+        return redisScript;
+    }
+
+    /**
+     * 闄愭祦鑴氭湰
+     */
+    private String limitScriptText()
+    {
+        return "local key = KEYS[1]\n" +
+                "local count = tonumber(ARGV[1])\n" +
+                "local time = tonumber(ARGV[2])\n" +
+                "local current = redis.call('get', key);\n" +
+                "if current and tonumber(current) > count then\n" +
+                "    return tonumber(current);\n" +
+                "end\n" +
+                "current = redis.call('incr', key)\n" +
+                "if tonumber(current) == 1 then\n" +
+                "    redis.call('expire', key, time)\n" +
+                "end\n" +
+                "return tonumber(current);";
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/config/ResourcesConfig.java b/jcdm-framework/src/main/java/com/jcdm/framework/config/ResourcesConfig.java
new file mode 100644
index 0000000..8ce3aea
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/config/ResourcesConfig.java
@@ -0,0 +1,73 @@
+package com.jcdm.framework.config;
+
+import java.util.concurrent.TimeUnit;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.CacheControl;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+import com.jcdm.common.config.MesConfig;
+import com.jcdm.common.constant.Constants;
+import com.jcdm.framework.interceptor.RepeatSubmitInterceptor;
+
+/**
+ * 閫氱敤閰嶇疆
+ * 
+ * @author jc
+ */
+@Configuration
+public class ResourcesConfig implements WebMvcConfigurer
+{
+    @Autowired
+    private RepeatSubmitInterceptor repeatSubmitInterceptor;
+
+    @Override
+    public void addResourceHandlers(ResourceHandlerRegistry registry)
+    {
+        /** 鏈湴鏂囦欢涓婁紶璺緞 */
+        registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**")
+                .addResourceLocations("file:" + MesConfig.getProfile() + "/");
+
+        /** swagger閰嶇疆 */
+        registry.addResourceHandler("/swagger-ui/**")
+                .addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/")
+                .setCacheControl(CacheControl.maxAge(5, TimeUnit.HOURS).cachePublic());;
+    }
+
+    /**
+     * 鑷畾涔夋嫤鎴鍒�
+     */
+    @Override
+    public void addInterceptors(InterceptorRegistry registry)
+    {
+        registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**");
+    }
+
+    /**
+     * 璺ㄥ煙閰嶇疆
+     */
+    @Bean
+    public CorsFilter corsFilter()
+    {
+        CorsConfiguration config = new CorsConfiguration();
+        config.setAllowCredentials(true);
+        // 璁剧疆璁块棶婧愬湴鍧�
+        config.addAllowedOriginPattern("*");
+        // 璁剧疆璁块棶婧愯姹傚ご
+        config.addAllowedHeader("*");
+        // 璁剧疆璁块棶婧愯姹傛柟娉�
+        config.addAllowedMethod("*");
+        // 鏈夋晥鏈� 1800绉�
+        config.setMaxAge(1800L);
+        // 娣诲姞鏄犲皠璺緞锛屾嫤鎴竴鍒囪姹�
+        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+        source.registerCorsConfiguration("/**", config);
+        // 杩斿洖鏂扮殑CorsFilter
+        return new CorsFilter(source);
+    }
+}
\ No newline at end of file
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/config/SecurityConfig.java b/jcdm-framework/src/main/java/com/jcdm/framework/config/SecurityConfig.java
new file mode 100644
index 0000000..b562f88
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/config/SecurityConfig.java
@@ -0,0 +1,148 @@
+package com.jcdm.framework.config;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.http.HttpMethod;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+import org.springframework.security.web.authentication.logout.LogoutFilter;
+import org.springframework.web.filter.CorsFilter;
+import com.jcdm.framework.config.properties.PermitAllUrlProperties;
+import com.jcdm.framework.security.filter.JwtAuthenticationTokenFilter;
+import com.jcdm.framework.security.handle.AuthenticationEntryPointImpl;
+import com.jcdm.framework.security.handle.LogoutSuccessHandlerImpl;
+
+/**
+ * spring security閰嶇疆
+ * 
+ * @author jc
+ */
+@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
+public class SecurityConfig extends WebSecurityConfigurerAdapter
+{
+    /**
+     * 鑷畾涔夌敤鎴疯璇侀�昏緫
+     */
+    @Autowired
+    private UserDetailsService userDetailsService;
+    
+    /**
+     * 璁よ瘉澶辫触澶勭悊绫�
+     */
+    @Autowired
+    private AuthenticationEntryPointImpl unauthorizedHandler;
+
+    /**
+     * 閫�鍑哄鐞嗙被
+     */
+    @Autowired
+    private LogoutSuccessHandlerImpl logoutSuccessHandler;
+
+    /**
+     * token璁よ瘉杩囨护鍣�
+     */
+    @Autowired
+    private JwtAuthenticationTokenFilter authenticationTokenFilter;
+    
+    /**
+     * 璺ㄥ煙杩囨护鍣�
+     */
+    @Autowired
+    private CorsFilter corsFilter;
+
+    /**
+     * 鍏佽鍖垮悕璁块棶鐨勫湴鍧�
+     */
+    @Autowired
+    private PermitAllUrlProperties permitAllUrl;
+
+    /**
+     * 瑙e喅 鏃犳硶鐩存帴娉ㄥ叆 AuthenticationManager
+     *
+     * @return
+     * @throws Exception
+     */
+    @Bean
+    @Override
+    public AuthenticationManager authenticationManagerBean() throws Exception
+    {
+        return super.authenticationManagerBean();
+    }
+
+    /**
+     * anyRequest          |   鍖归厤鎵�鏈夎姹傝矾寰�
+     * access              |   SpringEl琛ㄨ揪寮忕粨鏋滀负true鏃跺彲浠ヨ闂�
+     * anonymous           |   鍖垮悕鍙互璁块棶
+     * denyAll             |   鐢ㄦ埛涓嶈兘璁块棶
+     * fullyAuthenticated  |   鐢ㄦ埛瀹屽叏璁よ瘉鍙互璁块棶锛堥潪remember-me涓嬭嚜鍔ㄧ櫥褰曪級
+     * hasAnyAuthority     |   濡傛灉鏈夊弬鏁帮紝鍙傛暟琛ㄧず鏉冮檺锛屽垯鍏朵腑浠讳綍涓�涓潈闄愬彲浠ヨ闂�
+     * hasAnyRole          |   濡傛灉鏈夊弬鏁帮紝鍙傛暟琛ㄧず瑙掕壊锛屽垯鍏朵腑浠讳綍涓�涓鑹插彲浠ヨ闂�
+     * hasAuthority        |   濡傛灉鏈夊弬鏁帮紝鍙傛暟琛ㄧず鏉冮檺锛屽垯鍏舵潈闄愬彲浠ヨ闂�
+     * hasIpAddress        |   濡傛灉鏈夊弬鏁帮紝鍙傛暟琛ㄧずIP鍦板潃锛屽鏋滅敤鎴稩P鍜屽弬鏁板尮閰嶏紝鍒欏彲浠ヨ闂�
+     * hasRole             |   濡傛灉鏈夊弬鏁帮紝鍙傛暟琛ㄧず瑙掕壊锛屽垯鍏惰鑹插彲浠ヨ闂�
+     * permitAll           |   鐢ㄦ埛鍙互浠绘剰璁块棶
+     * rememberMe          |   鍏佽閫氳繃remember-me鐧诲綍鐨勭敤鎴疯闂�
+     * authenticated       |   鐢ㄦ埛鐧诲綍鍚庡彲璁块棶
+     */
+    @Override
+    protected void configure(HttpSecurity httpSecurity) throws Exception
+    {
+        // 娉ㄨВ鏍囪鍏佽鍖垮悕璁块棶鐨剈rl
+        ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = httpSecurity.authorizeRequests();
+        permitAllUrl.getUrls().forEach(url -> registry.antMatchers(url).permitAll());
+
+        httpSecurity
+                // CSRF绂佺敤锛屽洜涓轰笉浣跨敤session
+                .csrf().disable()
+                // 绂佺敤HTTP鍝嶅簲鏍囧ご
+                .headers().cacheControl().disable().and()
+                // 璁よ瘉澶辫触澶勭悊绫�
+                .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
+                // 鍩轰簬token锛屾墍浠ヤ笉闇�瑕乻ession
+                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
+                // 杩囨护璇锋眰
+                .authorizeRequests()
+                // 瀵逛簬鐧诲綍login 娉ㄥ唽register 楠岃瘉鐮乧aptchaImage 鍏佽鍖垮悕璁块棶
+                .antMatchers("/login", "/register", "/captchaImage","/websocket/**","/postWebsocket/**").permitAll()
+                // 闈欐�佽祫婧愶紝鍙尶鍚嶈闂�
+                .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
+                .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()
+                // 闄や笂闈㈠鐨勬墍鏈夎姹傚叏閮ㄩ渶瑕侀壌鏉冭璇�
+                .anyRequest().authenticated()
+                .and()
+                .headers().frameOptions().disable();
+        // 娣诲姞Logout filter
+        httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler);
+        // 娣诲姞JWT filter
+        httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
+        // 娣诲姞CORS filter
+        httpSecurity.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class);
+        httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class);
+    }
+
+    /**
+     * 寮烘暎鍒楀搱甯屽姞瀵嗗疄鐜�
+     */
+    @Bean
+    public BCryptPasswordEncoder bCryptPasswordEncoder()
+    {
+        return new BCryptPasswordEncoder();
+    }
+
+    /**
+     * 韬唤璁よ瘉鎺ュ彛
+     */
+    @Override
+    protected void configure(AuthenticationManagerBuilder auth) throws Exception
+    {
+        auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/config/ServerConfig.java b/jcdm-framework/src/main/java/com/jcdm/framework/config/ServerConfig.java
new file mode 100644
index 0000000..fec3dab
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/config/ServerConfig.java
@@ -0,0 +1,32 @@
+package com.jcdm.framework.config;
+
+import javax.servlet.http.HttpServletRequest;
+import org.springframework.stereotype.Component;
+import com.jcdm.common.utils.ServletUtils;
+
+/**
+ * 鏈嶅姟鐩稿叧閰嶇疆
+ * 
+ * @author jc
+ */
+@Component
+public class ServerConfig
+{
+    /**
+     * 鑾峰彇瀹屾暣鐨勮姹傝矾寰勶紝鍖呮嫭锛氬煙鍚嶏紝绔彛锛屼笂涓嬫枃璁块棶璺緞
+     * 
+     * @return 鏈嶅姟鍦板潃
+     */
+    public String getUrl()
+    {
+        HttpServletRequest request = ServletUtils.getRequest();
+        return getDomain(request);
+    }
+
+    public static String getDomain(HttpServletRequest request)
+    {
+        StringBuffer url = request.getRequestURL();
+        String contextPath = request.getServletContext().getContextPath();
+        return url.delete(url.length() - request.getRequestURI().length(), url.length()).append(contextPath).toString();
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/config/ThreadPoolConfig.java b/jcdm-framework/src/main/java/com/jcdm/framework/config/ThreadPoolConfig.java
new file mode 100644
index 0000000..531a6e1
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/config/ThreadPoolConfig.java
@@ -0,0 +1,63 @@
+package com.jcdm.framework.config;
+
+import com.jcdm.common.utils.Threads;
+import org.apache.commons.lang3.concurrent.BasicThreadFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.ThreadPoolExecutor;
+
+/**
+ * 绾跨▼姹犻厤缃�
+ *
+ * @author jc
+ **/
+@Configuration
+public class ThreadPoolConfig
+{
+    // 鏍稿績绾跨▼姹犲ぇ灏�
+    private int corePoolSize = 50;
+
+    // 鏈�澶у彲鍒涘缓鐨勭嚎绋嬫暟
+    private int maxPoolSize = 200;
+
+    // 闃熷垪鏈�澶ч暱搴�
+    private int queueCapacity = 1000;
+
+    // 绾跨▼姹犵淮鎶ょ嚎绋嬫墍鍏佽鐨勭┖闂叉椂闂�
+    private int keepAliveSeconds = 300;
+
+    @Bean(name = "threadPoolTaskExecutor")
+    public ThreadPoolTaskExecutor threadPoolTaskExecutor()
+    {
+        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+        executor.setMaxPoolSize(maxPoolSize);
+        executor.setCorePoolSize(corePoolSize);
+        executor.setQueueCapacity(queueCapacity);
+        executor.setKeepAliveSeconds(keepAliveSeconds);
+        // 绾跨▼姹犲鎷掔粷浠诲姟(鏃犵嚎绋嬪彲鐢�)鐨勫鐞嗙瓥鐣�
+        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+        return executor;
+    }
+
+    /**
+     * 鎵ц鍛ㄦ湡鎬ф垨瀹氭椂浠诲姟
+     */
+    @Bean(name = "scheduledExecutorService")
+    protected ScheduledExecutorService scheduledExecutorService()
+    {
+        return new ScheduledThreadPoolExecutor(corePoolSize,
+                new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(),
+                new ThreadPoolExecutor.CallerRunsPolicy())
+        {
+            @Override
+            protected void afterExecute(Runnable r, Throwable t)
+            {
+                super.afterExecute(r, t);
+                Threads.printException(r, t);
+            }
+        };
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/config/properties/DruidProperties.java b/jcdm-framework/src/main/java/com/jcdm/framework/config/properties/DruidProperties.java
new file mode 100644
index 0000000..ee53f7f
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/config/properties/DruidProperties.java
@@ -0,0 +1,89 @@
+package com.jcdm.framework.config.properties;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+import com.alibaba.druid.pool.DruidDataSource;
+
+/**
+ * druid 閰嶇疆灞炴��
+ * 
+ * @author jc
+ */
+@Configuration
+public class DruidProperties
+{
+    @Value("${spring.datasource.druid.initialSize}")
+    private int initialSize;
+
+    @Value("${spring.datasource.druid.minIdle}")
+    private int minIdle;
+
+    @Value("${spring.datasource.druid.maxActive}")
+    private int maxActive;
+
+    @Value("${spring.datasource.druid.maxWait}")
+    private int maxWait;
+
+    @Value("${spring.datasource.druid.connectTimeout}")
+    private int connectTimeout;
+
+    @Value("${spring.datasource.druid.socketTimeout}")
+    private int socketTimeout;
+
+    @Value("${spring.datasource.druid.timeBetweenEvictionRunsMillis}")
+    private int timeBetweenEvictionRunsMillis;
+
+    @Value("${spring.datasource.druid.minEvictableIdleTimeMillis}")
+    private int minEvictableIdleTimeMillis;
+
+    @Value("${spring.datasource.druid.maxEvictableIdleTimeMillis}")
+    private int maxEvictableIdleTimeMillis;
+
+    @Value("${spring.datasource.druid.validationQuery}")
+    private String validationQuery;
+
+    @Value("${spring.datasource.druid.testWhileIdle}")
+    private boolean testWhileIdle;
+
+    @Value("${spring.datasource.druid.testOnBorrow}")
+    private boolean testOnBorrow;
+
+    @Value("${spring.datasource.druid.testOnReturn}")
+    private boolean testOnReturn;
+
+    public DruidDataSource dataSource(DruidDataSource datasource)
+    {
+        /** 閰嶇疆鍒濆鍖栧ぇ灏忋�佹渶灏忋�佹渶澶� */
+        datasource.setInitialSize(initialSize);
+        datasource.setMaxActive(maxActive);
+        datasource.setMinIdle(minIdle);
+
+        /** 閰嶇疆鑾峰彇杩炴帴绛夊緟瓒呮椂鐨勬椂闂� */
+        datasource.setMaxWait(maxWait);
+        
+        /** 閰嶇疆椹卞姩杩炴帴瓒呮椂鏃堕棿锛屾娴嬫暟鎹簱寤虹珛杩炴帴鐨勮秴鏃舵椂闂达紝鍗曚綅鏄绉� */
+        datasource.setConnectTimeout(connectTimeout);
+        
+        /** 閰嶇疆缃戠粶瓒呮椂鏃堕棿锛岀瓑寰呮暟鎹簱鎿嶄綔瀹屾垚鐨勭綉缁滆秴鏃舵椂闂达紝鍗曚綅鏄绉� */
+        datasource.setSocketTimeout(socketTimeout);
+
+        /** 閰嶇疆闂撮殧澶氫箙鎵嶈繘琛屼竴娆℃娴嬶紝妫�娴嬮渶瑕佸叧闂殑绌洪棽杩炴帴锛屽崟浣嶆槸姣 */
+        datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
+
+        /** 閰嶇疆涓�涓繛鎺ュ湪姹犱腑鏈�灏忋�佹渶澶х敓瀛樼殑鏃堕棿锛屽崟浣嶆槸姣 */
+        datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
+        datasource.setMaxEvictableIdleTimeMillis(maxEvictableIdleTimeMillis);
+
+        /**
+         * 鐢ㄦ潵妫�娴嬭繛鎺ユ槸鍚︽湁鏁堢殑sql锛岃姹傛槸涓�涓煡璇㈣鍙ワ紝甯哥敤select 'x'銆傚鏋渧alidationQuery涓簄ull锛宼estOnBorrow銆乼estOnReturn銆乼estWhileIdle閮戒笉浼氳捣浣滅敤銆�
+         */
+        datasource.setValidationQuery(validationQuery);
+        /** 寤鸿閰嶇疆涓簍rue锛屼笉褰卞搷鎬ц兘锛屽苟涓斾繚璇佸畨鍏ㄦ�с�傜敵璇疯繛鎺ョ殑鏃跺�欐娴嬶紝濡傛灉绌洪棽鏃堕棿澶т簬timeBetweenEvictionRunsMillis锛屾墽琛寁alidationQuery妫�娴嬭繛鎺ユ槸鍚︽湁鏁堛�� */
+        datasource.setTestWhileIdle(testWhileIdle);
+        /** 鐢宠杩炴帴鏃舵墽琛寁alidationQuery妫�娴嬭繛鎺ユ槸鍚︽湁鏁堬紝鍋氫簡杩欎釜閰嶇疆浼氶檷浣庢�ц兘銆� */
+        datasource.setTestOnBorrow(testOnBorrow);
+        /** 褰掕繕杩炴帴鏃舵墽琛寁alidationQuery妫�娴嬭繛鎺ユ槸鍚︽湁鏁堬紝鍋氫簡杩欎釜閰嶇疆浼氶檷浣庢�ц兘銆� */
+        datasource.setTestOnReturn(testOnReturn);
+        return datasource;
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/config/properties/PermitAllUrlProperties.java b/jcdm-framework/src/main/java/com/jcdm/framework/config/properties/PermitAllUrlProperties.java
new file mode 100644
index 0000000..c3b603b
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/config/properties/PermitAllUrlProperties.java
@@ -0,0 +1,73 @@
+package com.jcdm.framework.config.properties;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.regex.Pattern;
+import org.apache.commons.lang3.RegExUtils;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.annotation.AnnotationUtils;
+import org.springframework.web.method.HandlerMethod;
+import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
+import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
+import com.jcdm.common.annotation.Anonymous;
+
+/**
+ * 璁剧疆Anonymous娉ㄨВ鍏佽鍖垮悕璁块棶鐨剈rl
+ * 
+ * @author jc
+ */
+@Configuration
+public class PermitAllUrlProperties implements InitializingBean, ApplicationContextAware
+{
+    private static final Pattern PATTERN = Pattern.compile("\\{(.*?)\\}");
+
+    private ApplicationContext applicationContext;
+
+    private List<String> urls = new ArrayList<>();
+
+    public String ASTERISK = "*";
+
+    @Override
+    public void afterPropertiesSet()
+    {
+        RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
+        Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();
+
+        map.keySet().forEach(info -> {
+            HandlerMethod handlerMethod = map.get(info);
+
+            // 鑾峰彇鏂规硶涓婅竟鐨勬敞瑙� 鏇夸唬path variable 涓� *
+            Anonymous method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Anonymous.class);
+            Optional.ofNullable(method).ifPresent(anonymous -> Objects.requireNonNull(info.getPatternsCondition().getPatterns())
+                    .forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK))));
+
+            // 鑾峰彇绫讳笂杈圭殑娉ㄨВ, 鏇夸唬path variable 涓� *
+            Anonymous controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), Anonymous.class);
+            Optional.ofNullable(controller).ifPresent(anonymous -> Objects.requireNonNull(info.getPatternsCondition().getPatterns())
+                    .forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK))));
+        });
+    }
+
+    @Override
+    public void setApplicationContext(ApplicationContext context) throws BeansException
+    {
+        this.applicationContext = context;
+    }
+
+    public List<String> getUrls()
+    {
+        return urls;
+    }
+
+    public void setUrls(List<String> urls)
+    {
+        this.urls = urls;
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/datasource/DynamicDataSource.java b/jcdm-framework/src/main/java/com/jcdm/framework/datasource/DynamicDataSource.java
new file mode 100644
index 0000000..ab61689
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/datasource/DynamicDataSource.java
@@ -0,0 +1,26 @@
+package com.jcdm.framework.datasource;
+
+import java.util.Map;
+import javax.sql.DataSource;
+import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
+
+/**
+ * 鍔ㄦ�佹暟鎹簮
+ * 
+ * @author jc
+ */
+public class DynamicDataSource extends AbstractRoutingDataSource
+{
+    public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources)
+    {
+        super.setDefaultTargetDataSource(defaultTargetDataSource);
+        super.setTargetDataSources(targetDataSources);
+        super.afterPropertiesSet();
+    }
+
+    @Override
+    protected Object determineCurrentLookupKey()
+    {
+        return DynamicDataSourceContextHolder.getDataSourceType();
+    }
+}
\ No newline at end of file
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/datasource/DynamicDataSourceContextHolder.java b/jcdm-framework/src/main/java/com/jcdm/framework/datasource/DynamicDataSourceContextHolder.java
new file mode 100644
index 0000000..7935570
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/datasource/DynamicDataSourceContextHolder.java
@@ -0,0 +1,45 @@
+package com.jcdm.framework.datasource;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 鏁版嵁婧愬垏鎹㈠鐞�
+ * 
+ * @author jc
+ */
+public class DynamicDataSourceContextHolder
+{
+    public static final Logger log = LoggerFactory.getLogger(DynamicDataSourceContextHolder.class);
+
+    /**
+     * 浣跨敤ThreadLocal缁存姢鍙橀噺锛孴hreadLocal涓烘瘡涓娇鐢ㄨ鍙橀噺鐨勭嚎绋嬫彁渚涚嫭绔嬬殑鍙橀噺鍓湰锛�
+     * 鎵�浠ユ瘡涓�涓嚎绋嬮兘鍙互鐙珛鍦版敼鍙樿嚜宸辩殑鍓湰锛岃�屼笉浼氬奖鍝嶅叾瀹冪嚎绋嬫墍瀵瑰簲鐨勫壇鏈��
+     */
+    private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();
+
+    /**
+     * 璁剧疆鏁版嵁婧愮殑鍙橀噺
+     */
+    public static void setDataSourceType(String dsType)
+    {
+        log.info("鍒囨崲鍒皗}鏁版嵁婧�", dsType);
+        CONTEXT_HOLDER.set(dsType);
+    }
+
+    /**
+     * 鑾峰緱鏁版嵁婧愮殑鍙橀噺
+     */
+    public static String getDataSourceType()
+    {
+        return CONTEXT_HOLDER.get();
+    }
+
+    /**
+     * 娓呯┖鏁版嵁婧愬彉閲�
+     */
+    public static void clearDataSourceType()
+    {
+        CONTEXT_HOLDER.remove();
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/interceptor/RepeatSubmitInterceptor.java b/jcdm-framework/src/main/java/com/jcdm/framework/interceptor/RepeatSubmitInterceptor.java
new file mode 100644
index 0000000..c4d518f
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/interceptor/RepeatSubmitInterceptor.java
@@ -0,0 +1,56 @@
+package com.jcdm.framework.interceptor;
+
+import java.lang.reflect.Method;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.stereotype.Component;
+import org.springframework.web.method.HandlerMethod;
+import org.springframework.web.servlet.HandlerInterceptor;
+import com.alibaba.fastjson2.JSON;
+import com.jcdm.common.annotation.RepeatSubmit;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.utils.ServletUtils;
+
+/**
+ * 闃叉閲嶅鎻愪氦鎷︽埅鍣�
+ *
+ * @author jc
+ */
+@Component
+public abstract class RepeatSubmitInterceptor implements HandlerInterceptor
+{
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
+    {
+        if (handler instanceof HandlerMethod)
+        {
+            HandlerMethod handlerMethod = (HandlerMethod) handler;
+            Method method = handlerMethod.getMethod();
+            RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class);
+            if (annotation != null)
+            {
+                if (this.isRepeatSubmit(request, annotation))
+                {
+                    AjaxResult ajaxResult = AjaxResult.error(annotation.message());
+                    ServletUtils.renderString(response, JSON.toJSONString(ajaxResult));
+                    return false;
+                }
+            }
+            return true;
+        }
+        else
+        {
+            return true;
+        }
+    }
+
+    /**
+     * 楠岃瘉鏄惁閲嶅鎻愪氦鐢卞瓙绫诲疄鐜板叿浣撶殑闃查噸澶嶆彁浜ょ殑瑙勫垯
+     *
+     * @param request 璇锋眰淇℃伅
+     * @param annotation 闃查噸澶嶆敞瑙e弬鏁�
+     * @return 缁撴灉
+     * @throws Exception
+     */
+    public abstract boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation);
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/interceptor/impl/SameUrlDataInterceptor.java b/jcdm-framework/src/main/java/com/jcdm/framework/interceptor/impl/SameUrlDataInterceptor.java
new file mode 100644
index 0000000..325519c
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/interceptor/impl/SameUrlDataInterceptor.java
@@ -0,0 +1,110 @@
+package com.jcdm.framework.interceptor.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import javax.servlet.http.HttpServletRequest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import com.alibaba.fastjson2.JSON;
+import com.jcdm.common.annotation.RepeatSubmit;
+import com.jcdm.common.constant.CacheConstants;
+import com.jcdm.common.core.redis.RedisCache;
+import com.jcdm.common.filter.RepeatedlyRequestWrapper;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.common.utils.http.HttpHelper;
+import com.jcdm.framework.interceptor.RepeatSubmitInterceptor;
+
+/**
+ * 鍒ゆ柇璇锋眰url鍜屾暟鎹槸鍚﹀拰涓婁竴娆$浉鍚岋紝
+ * 濡傛灉鍜屼笂娆$浉鍚岋紝鍒欐槸閲嶅鎻愪氦琛ㄥ崟銆� 鏈夋晥鏃堕棿涓�10绉掑唴銆�
+ * 
+ * @author jc
+ */
+@Component
+public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
+{
+    public final String REPEAT_PARAMS = "repeatParams";
+
+    public final String REPEAT_TIME = "repeatTime";
+
+    // 浠ょ墝鑷畾涔夋爣璇�
+    @Value("${token.header}")
+    private String header;
+
+    @Autowired
+    private RedisCache redisCache;
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation)
+    {
+        String nowParams = "";
+        if (request instanceof RepeatedlyRequestWrapper)
+        {
+            RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request;
+            nowParams = HttpHelper.getBodyString(repeatedlyRequest);
+        }
+
+        // body鍙傛暟涓虹┖锛岃幏鍙朠arameter鐨勬暟鎹�
+        if (StringUtils.isEmpty(nowParams))
+        {
+            nowParams = JSON.toJSONString(request.getParameterMap());
+        }
+        Map<String, Object> nowDataMap = new HashMap<String, Object>();
+        nowDataMap.put(REPEAT_PARAMS, nowParams);
+        nowDataMap.put(REPEAT_TIME, System.currentTimeMillis());
+
+        // 璇锋眰鍦板潃锛堜綔涓哄瓨鏀綾ache鐨刱ey鍊硷級
+        String url = request.getRequestURI();
+
+        // 鍞竴鍊硷紙娌℃湁娑堟伅澶村垯浣跨敤璇锋眰鍦板潃锛�
+        String submitKey = StringUtils.trimToEmpty(request.getHeader(header));
+
+        // 鍞竴鏍囪瘑锛堟寚瀹歬ey + url + 娑堟伅澶达級
+        String cacheRepeatKey = CacheConstants.REPEAT_SUBMIT_KEY + url + submitKey;
+
+        Object sessionObj = redisCache.getCacheObject(cacheRepeatKey);
+        if (sessionObj != null)
+        {
+            Map<String, Object> sessionMap = (Map<String, Object>) sessionObj;
+            if (sessionMap.containsKey(url))
+            {
+                Map<String, Object> preDataMap = (Map<String, Object>) sessionMap.get(url);
+                if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap, annotation.interval()))
+                {
+                    return true;
+                }
+            }
+        }
+        Map<String, Object> cacheMap = new HashMap<String, Object>();
+        cacheMap.put(url, nowDataMap);
+        redisCache.setCacheObject(cacheRepeatKey, cacheMap, annotation.interval(), TimeUnit.MILLISECONDS);
+        return false;
+    }
+
+    /**
+     * 鍒ゆ柇鍙傛暟鏄惁鐩稿悓
+     */
+    private boolean compareParams(Map<String, Object> nowMap, Map<String, Object> preMap)
+    {
+        String nowParams = (String) nowMap.get(REPEAT_PARAMS);
+        String preParams = (String) preMap.get(REPEAT_PARAMS);
+        return nowParams.equals(preParams);
+    }
+
+    /**
+     * 鍒ゆ柇涓ゆ闂撮殧鏃堕棿
+     */
+    private boolean compareTime(Map<String, Object> nowMap, Map<String, Object> preMap, int interval)
+    {
+        long time1 = (Long) nowMap.get(REPEAT_TIME);
+        long time2 = (Long) preMap.get(REPEAT_TIME);
+        if ((time1 - time2) < interval)
+        {
+            return true;
+        }
+        return false;
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/manager/AsyncManager.java b/jcdm-framework/src/main/java/com/jcdm/framework/manager/AsyncManager.java
new file mode 100644
index 0000000..8b47de5
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/manager/AsyncManager.java
@@ -0,0 +1,55 @@
+package com.jcdm.framework.manager;
+
+import java.util.TimerTask;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import com.jcdm.common.utils.Threads;
+import com.jcdm.common.utils.spring.SpringUtils;
+
+/**
+ * 寮傛浠诲姟绠$悊鍣�
+ * 
+ * @author jc
+ */
+public class AsyncManager
+{
+    /**
+     * 鎿嶄綔寤惰繜10姣
+     */
+    private final int OPERATE_DELAY_TIME = 10;
+
+    /**
+     * 寮傛鎿嶄綔浠诲姟璋冨害绾跨▼姹�
+     */
+    private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService");
+
+    /**
+     * 鍗曚緥妯″紡
+     */
+    private AsyncManager(){}
+
+    private static AsyncManager me = new AsyncManager();
+
+    public static AsyncManager me()
+    {
+        return me;
+    }
+
+    /**
+     * 鎵ц浠诲姟
+     * 
+     * @param task 浠诲姟
+     */
+    public void execute(TimerTask task)
+    {
+        executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);
+    }
+
+    /**
+     * 鍋滄浠诲姟绾跨▼姹�
+     */
+    public void shutdown()
+    {
+        Threads.shutdownAndAwaitTermination(executor);
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/manager/ShutdownManager.java b/jcdm-framework/src/main/java/com/jcdm/framework/manager/ShutdownManager.java
new file mode 100644
index 0000000..2393556
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/manager/ShutdownManager.java
@@ -0,0 +1,39 @@
+package com.jcdm.framework.manager;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import javax.annotation.PreDestroy;
+
+/**
+ * 纭繚搴旂敤閫�鍑烘椂鑳藉叧闂悗鍙扮嚎绋�
+ *
+ * @author jc
+ */
+@Component
+public class ShutdownManager
+{
+    private static final Logger logger = LoggerFactory.getLogger("sys-user");
+
+    @PreDestroy
+    public void destroy()
+    {
+        shutdownAsyncManager();
+    }
+
+    /**
+     * 鍋滄寮傛鎵ц浠诲姟
+     */
+    private void shutdownAsyncManager()
+    {
+        try
+        {
+            logger.info("====鍏抽棴鍚庡彴浠诲姟浠诲姟绾跨▼姹�====");
+            AsyncManager.me().shutdown();
+        }
+        catch (Exception e)
+        {
+            logger.error(e.getMessage(), e);
+        }
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/manager/factory/AsyncFactory.java b/jcdm-framework/src/main/java/com/jcdm/framework/manager/factory/AsyncFactory.java
new file mode 100644
index 0000000..58a0ce4
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/manager/factory/AsyncFactory.java
@@ -0,0 +1,102 @@
+package com.jcdm.framework.manager.factory;
+
+import java.util.TimerTask;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.jcdm.common.constant.Constants;
+import com.jcdm.common.utils.LogUtils;
+import com.jcdm.common.utils.ServletUtils;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.common.utils.ip.AddressUtils;
+import com.jcdm.common.utils.ip.IpUtils;
+import com.jcdm.common.utils.spring.SpringUtils;
+import com.jcdm.system.domain.SysLogininfor;
+import com.jcdm.system.domain.SysOperLog;
+import com.jcdm.system.service.ISysLogininforService;
+import com.jcdm.system.service.ISysOperLogService;
+import eu.bitwalker.useragentutils.UserAgent;
+
+/**
+ * 寮傛宸ュ巶锛堜骇鐢熶换鍔$敤锛�
+ * 
+ * @author jc
+ */
+public class AsyncFactory
+{
+    private static final Logger sys_user_logger = LoggerFactory.getLogger("sys-user");
+
+    /**
+     * 璁板綍鐧诲綍淇℃伅
+     * 
+     * @param username 鐢ㄦ埛鍚�
+     * @param status 鐘舵��
+     * @param message 娑堟伅
+     * @param args 鍒楄〃
+     * @return 浠诲姟task
+     */
+    public static TimerTask recordLogininfor(final String username, final String status, final String message,
+            final Object... args)
+    {
+        final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
+        final String ip = IpUtils.getIpAddr();
+        return new TimerTask()
+        {
+            @Override
+            public void run()
+            {
+                String address = AddressUtils.getRealAddressByIP(ip);
+                StringBuilder s = new StringBuilder();
+                s.append(LogUtils.getBlock(ip));
+                s.append(address);
+                s.append(LogUtils.getBlock(username));
+                s.append(LogUtils.getBlock(status));
+                s.append(LogUtils.getBlock(message));
+                // 鎵撳嵃淇℃伅鍒版棩蹇�
+                sys_user_logger.info(s.toString(), args);
+                // 鑾峰彇瀹㈡埛绔搷浣滅郴缁�
+                String os = userAgent.getOperatingSystem().getName();
+                // 鑾峰彇瀹㈡埛绔祻瑙堝櫒
+                String browser = userAgent.getBrowser().getName();
+                // 灏佽瀵硅薄
+                SysLogininfor logininfor = new SysLogininfor();
+                logininfor.setUserName(username);
+                logininfor.setIpaddr(ip);
+                logininfor.setLoginLocation(address);
+                logininfor.setBrowser(browser);
+                logininfor.setOs(os);
+                logininfor.setMsg(message);
+                // 鏃ュ織鐘舵��
+                if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER))
+                {
+                    logininfor.setStatus(Constants.SUCCESS);
+                }
+                else if (Constants.LOGIN_FAIL.equals(status))
+                {
+                    logininfor.setStatus(Constants.FAIL);
+                }
+                // 鎻掑叆鏁版嵁
+                SpringUtils.getBean(ISysLogininforService.class).insertLogininfor(logininfor);
+            }
+        };
+    }
+
+    /**
+     * 鎿嶄綔鏃ュ織璁板綍
+     * 
+     * @param operLog 鎿嶄綔鏃ュ織淇℃伅
+     * @return 浠诲姟task
+     */
+    public static TimerTask recordOper(final SysOperLog operLog)
+    {
+        return new TimerTask()
+        {
+            @Override
+            public void run()
+            {
+                // 杩滅▼鏌ヨ鎿嶄綔鍦扮偣
+                operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp()));
+                SpringUtils.getBean(ISysOperLogService.class).insertOperlog(operLog);
+            }
+        };
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/security/context/AuthenticationContextHolder.java b/jcdm-framework/src/main/java/com/jcdm/framework/security/context/AuthenticationContextHolder.java
new file mode 100644
index 0000000..0852a0d
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/security/context/AuthenticationContextHolder.java
@@ -0,0 +1,28 @@
+package com.jcdm.framework.security.context;
+
+import org.springframework.security.core.Authentication;
+
+/**
+ * 韬唤楠岃瘉淇℃伅
+ * 
+ * @author jc
+ */
+public class AuthenticationContextHolder
+{
+    private static final ThreadLocal<Authentication> contextHolder = new ThreadLocal<>();
+
+    public static Authentication getContext()
+    {
+        return contextHolder.get();
+    }
+
+    public static void setContext(Authentication context)
+    {
+        contextHolder.set(context);
+    }
+
+    public static void clearContext()
+    {
+        contextHolder.remove();
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/security/context/PermissionContextHolder.java b/jcdm-framework/src/main/java/com/jcdm/framework/security/context/PermissionContextHolder.java
new file mode 100644
index 0000000..dd4233e
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/security/context/PermissionContextHolder.java
@@ -0,0 +1,27 @@
+package com.jcdm.framework.security.context;
+
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.RequestContextHolder;
+import com.jcdm.common.core.text.Convert;
+
+/**
+ * 鏉冮檺淇℃伅
+ * 
+ * @author jc
+ */
+public class PermissionContextHolder
+{
+    private static final String PERMISSION_CONTEXT_ATTRIBUTES = "PERMISSION_CONTEXT";
+
+    public static void setContext(String permission)
+    {
+        RequestContextHolder.currentRequestAttributes().setAttribute(PERMISSION_CONTEXT_ATTRIBUTES, permission,
+                RequestAttributes.SCOPE_REQUEST);
+    }
+
+    public static String getContext()
+    {
+        return Convert.toStr(RequestContextHolder.currentRequestAttributes().getAttribute(PERMISSION_CONTEXT_ATTRIBUTES,
+                RequestAttributes.SCOPE_REQUEST));
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/security/filter/JwtAuthenticationTokenFilter.java b/jcdm-framework/src/main/java/com/jcdm/framework/security/filter/JwtAuthenticationTokenFilter.java
new file mode 100644
index 0000000..2acb56a
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/security/filter/JwtAuthenticationTokenFilter.java
@@ -0,0 +1,44 @@
+package com.jcdm.framework.security.filter;
+
+import java.io.IOException;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
+import org.springframework.stereotype.Component;
+import org.springframework.web.filter.OncePerRequestFilter;
+import com.jcdm.common.core.domain.model.LoginUser;
+import com.jcdm.common.utils.SecurityUtils;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.framework.web.service.TokenService;
+
+/**
+ * token杩囨护鍣� 楠岃瘉token鏈夋晥鎬�
+ * 
+ * @author jc
+ */
+@Component
+public class JwtAuthenticationTokenFilter extends OncePerRequestFilter
+{
+    @Autowired
+    private TokenService tokenService;
+
+    @Override
+    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
+            throws ServletException, IOException
+    {
+        LoginUser loginUser = tokenService.getLoginUser(request);
+        if (StringUtils.isNotNull(loginUser) && StringUtils.isNull(SecurityUtils.getAuthentication()))
+        {
+            tokenService.verifyToken(loginUser);
+            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
+            authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
+            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
+        }
+        chain.doFilter(request, response);
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/security/handle/AuthenticationEntryPointImpl.java b/jcdm-framework/src/main/java/com/jcdm/framework/security/handle/AuthenticationEntryPointImpl.java
new file mode 100644
index 0000000..01ba128
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/security/handle/AuthenticationEntryPointImpl.java
@@ -0,0 +1,34 @@
+package com.jcdm.framework.security.handle;
+
+import java.io.IOException;
+import java.io.Serializable;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.stereotype.Component;
+import com.alibaba.fastjson2.JSON;
+import com.jcdm.common.constant.HttpStatus;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.utils.ServletUtils;
+import com.jcdm.common.utils.StringUtils;
+
+/**
+ * 璁よ瘉澶辫触澶勭悊绫� 杩斿洖鏈巿鏉�
+ * 
+ * @author jc
+ */
+@Component
+public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint, Serializable
+{
+    private static final long serialVersionUID = -8970718410437077606L;
+
+    @Override
+    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e)
+            throws IOException
+    {
+        int code = HttpStatus.UNAUTHORIZED;
+        String msg = StringUtils.format("璇锋眰璁块棶锛歿}锛岃璇佸け璐ワ紝鏃犳硶璁块棶绯荤粺璧勬簮", request.getRequestURI());
+        ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.error(code, msg)));
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/security/handle/LogoutSuccessHandlerImpl.java b/jcdm-framework/src/main/java/com/jcdm/framework/security/handle/LogoutSuccessHandlerImpl.java
new file mode 100644
index 0000000..d9a8d29
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/security/handle/LogoutSuccessHandlerImpl.java
@@ -0,0 +1,52 @@
+package com.jcdm.framework.security.handle;
+
+import java.io.IOException;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
+import com.alibaba.fastjson2.JSON;
+import com.jcdm.common.constant.Constants;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.core.domain.model.LoginUser;
+import com.jcdm.common.utils.ServletUtils;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.framework.manager.AsyncManager;
+import com.jcdm.framework.manager.factory.AsyncFactory;
+import com.jcdm.framework.web.service.TokenService;
+
+/**
+ * 鑷畾涔夐��鍑哄鐞嗙被 杩斿洖鎴愬姛
+ * 
+ * @author jc
+ */
+@Configuration
+public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler
+{
+    @Autowired
+    private TokenService tokenService;
+
+    /**
+     * 閫�鍑哄鐞�
+     * 
+     * @return
+     */
+    @Override
+    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
+            throws IOException, ServletException
+    {
+        LoginUser loginUser = tokenService.getLoginUser(request);
+        if (StringUtils.isNotNull(loginUser))
+        {
+            String userName = loginUser.getUsername();
+            // 鍒犻櫎鐢ㄦ埛缂撳瓨璁板綍
+            tokenService.delLoginUser(loginUser.getToken());
+            // 璁板綍鐢ㄦ埛閫�鍑烘棩蹇�
+            AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, Constants.LOGOUT, "閫�鍑烘垚鍔�"));
+        }
+        ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.success("閫�鍑烘垚鍔�")));
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/web/domain/Server.java b/jcdm-framework/src/main/java/com/jcdm/framework/web/domain/Server.java
new file mode 100644
index 0000000..c0c3728
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/web/domain/Server.java
@@ -0,0 +1,240 @@
+package com.jcdm.framework.web.domain;
+
+import java.net.UnknownHostException;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Properties;
+import com.jcdm.common.utils.Arith;
+import com.jcdm.common.utils.ip.IpUtils;
+import com.jcdm.framework.web.domain.server.Cpu;
+import com.jcdm.framework.web.domain.server.Jvm;
+import com.jcdm.framework.web.domain.server.Mem;
+import com.jcdm.framework.web.domain.server.Sys;
+import com.jcdm.framework.web.domain.server.SysFile;
+import oshi.SystemInfo;
+import oshi.hardware.CentralProcessor;
+import oshi.hardware.CentralProcessor.TickType;
+import oshi.hardware.GlobalMemory;
+import oshi.hardware.HardwareAbstractionLayer;
+import oshi.software.os.FileSystem;
+import oshi.software.os.OSFileStore;
+import oshi.software.os.OperatingSystem;
+import oshi.util.Util;
+
+/**
+ * 鏈嶅姟鍣ㄧ浉鍏充俊鎭�
+ * 
+ * @author jc
+ */
+public class Server
+{
+    private static final int OSHI_WAIT_SECOND = 1000;
+    
+    /**
+     * CPU鐩稿叧淇℃伅
+     */
+    private Cpu cpu = new Cpu();
+
+    /**
+     * 鍏у瓨鐩稿叧淇℃伅
+     */
+    private Mem mem = new Mem();
+
+    /**
+     * JVM鐩稿叧淇℃伅
+     */
+    private Jvm jvm = new Jvm();
+
+    /**
+     * 鏈嶅姟鍣ㄧ浉鍏充俊鎭�
+     */
+    private Sys sys = new Sys();
+
+    /**
+     * 纾佺洏鐩稿叧淇℃伅
+     */
+    private List<SysFile> sysFiles = new LinkedList<SysFile>();
+
+    public Cpu getCpu()
+    {
+        return cpu;
+    }
+
+    public void setCpu(Cpu cpu)
+    {
+        this.cpu = cpu;
+    }
+
+    public Mem getMem()
+    {
+        return mem;
+    }
+
+    public void setMem(Mem mem)
+    {
+        this.mem = mem;
+    }
+
+    public Jvm getJvm()
+    {
+        return jvm;
+    }
+
+    public void setJvm(Jvm jvm)
+    {
+        this.jvm = jvm;
+    }
+
+    public Sys getSys()
+    {
+        return sys;
+    }
+
+    public void setSys(Sys sys)
+    {
+        this.sys = sys;
+    }
+
+    public List<SysFile> getSysFiles()
+    {
+        return sysFiles;
+    }
+
+    public void setSysFiles(List<SysFile> sysFiles)
+    {
+        this.sysFiles = sysFiles;
+    }
+
+    public void copyTo() throws Exception
+    {
+        SystemInfo si = new SystemInfo();
+        HardwareAbstractionLayer hal = si.getHardware();
+
+        setCpuInfo(hal.getProcessor());
+
+        setMemInfo(hal.getMemory());
+
+        setSysInfo();
+
+        setJvmInfo();
+
+        setSysFiles(si.getOperatingSystem());
+    }
+
+    /**
+     * 璁剧疆CPU淇℃伅
+     */
+    private void setCpuInfo(CentralProcessor processor)
+    {
+        // CPU淇℃伅
+        long[] prevTicks = processor.getSystemCpuLoadTicks();
+        Util.sleep(OSHI_WAIT_SECOND);
+        long[] ticks = processor.getSystemCpuLoadTicks();
+        long nice = ticks[TickType.NICE.getIndex()] - prevTicks[TickType.NICE.getIndex()];
+        long irq = ticks[TickType.IRQ.getIndex()] - prevTicks[TickType.IRQ.getIndex()];
+        long softirq = ticks[TickType.SOFTIRQ.getIndex()] - prevTicks[TickType.SOFTIRQ.getIndex()];
+        long steal = ticks[TickType.STEAL.getIndex()] - prevTicks[TickType.STEAL.getIndex()];
+        long cSys = ticks[TickType.SYSTEM.getIndex()] - prevTicks[TickType.SYSTEM.getIndex()];
+        long user = ticks[TickType.USER.getIndex()] - prevTicks[TickType.USER.getIndex()];
+        long iowait = ticks[TickType.IOWAIT.getIndex()] - prevTicks[TickType.IOWAIT.getIndex()];
+        long idle = ticks[TickType.IDLE.getIndex()] - prevTicks[TickType.IDLE.getIndex()];
+        long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal;
+        cpu.setCpuNum(processor.getLogicalProcessorCount());
+        cpu.setTotal(totalCpu);
+        cpu.setSys(cSys);
+        cpu.setUsed(user);
+        cpu.setWait(iowait);
+        cpu.setFree(idle);
+    }
+
+    /**
+     * 璁剧疆鍐呭瓨淇℃伅
+     */
+    private void setMemInfo(GlobalMemory memory)
+    {
+        mem.setTotal(memory.getTotal());
+        mem.setUsed(memory.getTotal() - memory.getAvailable());
+        mem.setFree(memory.getAvailable());
+    }
+
+    /**
+     * 璁剧疆鏈嶅姟鍣ㄤ俊鎭�
+     */
+    private void setSysInfo()
+    {
+        Properties props = System.getProperties();
+        sys.setComputerName(IpUtils.getHostName());
+        sys.setComputerIp(IpUtils.getHostIp());
+        sys.setOsName(props.getProperty("os.name"));
+        sys.setOsArch(props.getProperty("os.arch"));
+        sys.setUserDir(props.getProperty("user.dir"));
+    }
+
+    /**
+     * 璁剧疆Java铏氭嫙鏈�
+     */
+    private void setJvmInfo() throws UnknownHostException
+    {
+        Properties props = System.getProperties();
+        jvm.setTotal(Runtime.getRuntime().totalMemory());
+        jvm.setMax(Runtime.getRuntime().maxMemory());
+        jvm.setFree(Runtime.getRuntime().freeMemory());
+        jvm.setVersion(props.getProperty("java.version"));
+        jvm.setHome(props.getProperty("java.home"));
+    }
+
+    /**
+     * 璁剧疆纾佺洏淇℃伅
+     */
+    private void setSysFiles(OperatingSystem os)
+    {
+        FileSystem fileSystem = os.getFileSystem();
+        List<OSFileStore> fsArray = fileSystem.getFileStores();
+        for (OSFileStore fs : fsArray)
+        {
+            long free = fs.getUsableSpace();
+            long total = fs.getTotalSpace();
+            long used = total - free;
+            SysFile sysFile = new SysFile();
+            sysFile.setDirName(fs.getMount());
+            sysFile.setSysTypeName(fs.getType());
+            sysFile.setTypeName(fs.getName());
+            sysFile.setTotal(convertFileSize(total));
+            sysFile.setFree(convertFileSize(free));
+            sysFile.setUsed(convertFileSize(used));
+            sysFile.setUsage(Arith.mul(Arith.div(used, total, 4), 100));
+            sysFiles.add(sysFile);
+        }
+    }
+
+    /**
+     * 瀛楄妭杞崲
+     * 
+     * @param size 瀛楄妭澶у皬
+     * @return 杞崲鍚庡��
+     */
+    public String convertFileSize(long size)
+    {
+        long kb = 1024;
+        long mb = kb * 1024;
+        long gb = mb * 1024;
+        if (size >= gb)
+        {
+            return String.format("%.1f GB", (float) size / gb);
+        }
+        else if (size >= mb)
+        {
+            float f = (float) size / mb;
+            return String.format(f > 100 ? "%.0f MB" : "%.1f MB", f);
+        }
+        else if (size >= kb)
+        {
+            float f = (float) size / kb;
+            return String.format(f > 100 ? "%.0f KB" : "%.1f KB", f);
+        }
+        else
+        {
+            return String.format("%d B", size);
+        }
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/web/domain/server/Cpu.java b/jcdm-framework/src/main/java/com/jcdm/framework/web/domain/server/Cpu.java
new file mode 100644
index 0000000..25e71d1
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/web/domain/server/Cpu.java
@@ -0,0 +1,101 @@
+package com.jcdm.framework.web.domain.server;
+
+import com.jcdm.common.utils.Arith;
+
+/**
+ * CPU鐩稿叧淇℃伅
+ * 
+ * @author jc
+ */
+public class Cpu
+{
+    /**
+     * 鏍稿績鏁�
+     */
+    private int cpuNum;
+
+    /**
+     * CPU鎬荤殑浣跨敤鐜�
+     */
+    private double total;
+
+    /**
+     * CPU绯荤粺浣跨敤鐜�
+     */
+    private double sys;
+
+    /**
+     * CPU鐢ㄦ埛浣跨敤鐜�
+     */
+    private double used;
+
+    /**
+     * CPU褰撳墠绛夊緟鐜�
+     */
+    private double wait;
+
+    /**
+     * CPU褰撳墠绌洪棽鐜�
+     */
+    private double free;
+
+    public int getCpuNum()
+    {
+        return cpuNum;
+    }
+
+    public void setCpuNum(int cpuNum)
+    {
+        this.cpuNum = cpuNum;
+    }
+
+    public double getTotal()
+    {
+        return Arith.round(Arith.mul(total, 100), 2);
+    }
+
+    public void setTotal(double total)
+    {
+        this.total = total;
+    }
+
+    public double getSys()
+    {
+        return Arith.round(Arith.mul(sys / total, 100), 2);
+    }
+
+    public void setSys(double sys)
+    {
+        this.sys = sys;
+    }
+
+    public double getUsed()
+    {
+        return Arith.round(Arith.mul(used / total, 100), 2);
+    }
+
+    public void setUsed(double used)
+    {
+        this.used = used;
+    }
+
+    public double getWait()
+    {
+        return Arith.round(Arith.mul(wait / total, 100), 2);
+    }
+
+    public void setWait(double wait)
+    {
+        this.wait = wait;
+    }
+
+    public double getFree()
+    {
+        return Arith.round(Arith.mul(free / total, 100), 2);
+    }
+
+    public void setFree(double free)
+    {
+        this.free = free;
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/web/domain/server/Jvm.java b/jcdm-framework/src/main/java/com/jcdm/framework/web/domain/server/Jvm.java
new file mode 100644
index 0000000..3ca96fc
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/web/domain/server/Jvm.java
@@ -0,0 +1,130 @@
+package com.jcdm.framework.web.domain.server;
+
+import java.lang.management.ManagementFactory;
+import com.jcdm.common.utils.Arith;
+import com.jcdm.common.utils.DateUtils;
+
+/**
+ * JVM鐩稿叧淇℃伅
+ * 
+ * @author jc
+ */
+public class Jvm
+{
+    /**
+     * 褰撳墠JVM鍗犵敤鐨勫唴瀛樻�绘暟(M)
+     */
+    private double total;
+
+    /**
+     * JVM鏈�澶у彲鐢ㄥ唴瀛樻�绘暟(M)
+     */
+    private double max;
+
+    /**
+     * JVM绌洪棽鍐呭瓨(M)
+     */
+    private double free;
+
+    /**
+     * JDK鐗堟湰
+     */
+    private String version;
+
+    /**
+     * JDK璺緞
+     */
+    private String home;
+
+    public double getTotal()
+    {
+        return Arith.div(total, (1024 * 1024), 2);
+    }
+
+    public void setTotal(double total)
+    {
+        this.total = total;
+    }
+
+    public double getMax()
+    {
+        return Arith.div(max, (1024 * 1024), 2);
+    }
+
+    public void setMax(double max)
+    {
+        this.max = max;
+    }
+
+    public double getFree()
+    {
+        return Arith.div(free, (1024 * 1024), 2);
+    }
+
+    public void setFree(double free)
+    {
+        this.free = free;
+    }
+
+    public double getUsed()
+    {
+        return Arith.div(total - free, (1024 * 1024), 2);
+    }
+
+    public double getUsage()
+    {
+        return Arith.mul(Arith.div(total - free, total, 4), 100);
+    }
+
+    /**
+     * 鑾峰彇JDK鍚嶇О
+     */
+    public String getName()
+    {
+        return ManagementFactory.getRuntimeMXBean().getVmName();
+    }
+
+    public String getVersion()
+    {
+        return version;
+    }
+
+    public void setVersion(String version)
+    {
+        this.version = version;
+    }
+
+    public String getHome()
+    {
+        return home;
+    }
+
+    public void setHome(String home)
+    {
+        this.home = home;
+    }
+
+    /**
+     * JDK鍚姩鏃堕棿
+     */
+    public String getStartTime()
+    {
+        return DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, DateUtils.getServerStartDate());
+    }
+
+    /**
+     * JDK杩愯鏃堕棿
+     */
+    public String getRunTime()
+    {
+        return DateUtils.timeDistance(DateUtils.getNowDate(), DateUtils.getServerStartDate());
+    }
+
+    /**
+     * 杩愯鍙傛暟
+     */
+    public String getInputArgs()
+    {
+        return ManagementFactory.getRuntimeMXBean().getInputArguments().toString();
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/web/domain/server/Mem.java b/jcdm-framework/src/main/java/com/jcdm/framework/web/domain/server/Mem.java
new file mode 100644
index 0000000..11675ca
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/web/domain/server/Mem.java
@@ -0,0 +1,61 @@
+package com.jcdm.framework.web.domain.server;
+
+import com.jcdm.common.utils.Arith;
+
+/**
+ * 鍏у瓨鐩稿叧淇℃伅
+ * 
+ * @author jc
+ */
+public class Mem
+{
+    /**
+     * 鍐呭瓨鎬婚噺
+     */
+    private double total;
+
+    /**
+     * 宸茬敤鍐呭瓨
+     */
+    private double used;
+
+    /**
+     * 鍓╀綑鍐呭瓨
+     */
+    private double free;
+
+    public double getTotal()
+    {
+        return Arith.div(total, (1024 * 1024 * 1024), 2);
+    }
+
+    public void setTotal(long total)
+    {
+        this.total = total;
+    }
+
+    public double getUsed()
+    {
+        return Arith.div(used, (1024 * 1024 * 1024), 2);
+    }
+
+    public void setUsed(long used)
+    {
+        this.used = used;
+    }
+
+    public double getFree()
+    {
+        return Arith.div(free, (1024 * 1024 * 1024), 2);
+    }
+
+    public void setFree(long free)
+    {
+        this.free = free;
+    }
+
+    public double getUsage()
+    {
+        return Arith.mul(Arith.div(used, total, 4), 100);
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/web/domain/server/Sys.java b/jcdm-framework/src/main/java/com/jcdm/framework/web/domain/server/Sys.java
new file mode 100644
index 0000000..07840b6
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/web/domain/server/Sys.java
@@ -0,0 +1,84 @@
+package com.jcdm.framework.web.domain.server;
+
+/**
+ * 绯荤粺鐩稿叧淇℃伅
+ * 
+ * @author jc
+ */
+public class Sys
+{
+    /**
+     * 鏈嶅姟鍣ㄥ悕绉�
+     */
+    private String computerName;
+
+    /**
+     * 鏈嶅姟鍣↖p
+     */
+    private String computerIp;
+
+    /**
+     * 椤圭洰璺緞
+     */
+    private String userDir;
+
+    /**
+     * 鎿嶄綔绯荤粺
+     */
+    private String osName;
+
+    /**
+     * 绯荤粺鏋舵瀯
+     */
+    private String osArch;
+
+    public String getComputerName()
+    {
+        return computerName;
+    }
+
+    public void setComputerName(String computerName)
+    {
+        this.computerName = computerName;
+    }
+
+    public String getComputerIp()
+    {
+        return computerIp;
+    }
+
+    public void setComputerIp(String computerIp)
+    {
+        this.computerIp = computerIp;
+    }
+
+    public String getUserDir()
+    {
+        return userDir;
+    }
+
+    public void setUserDir(String userDir)
+    {
+        this.userDir = userDir;
+    }
+
+    public String getOsName()
+    {
+        return osName;
+    }
+
+    public void setOsName(String osName)
+    {
+        this.osName = osName;
+    }
+
+    public String getOsArch()
+    {
+        return osArch;
+    }
+
+    public void setOsArch(String osArch)
+    {
+        this.osArch = osArch;
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/web/domain/server/SysFile.java b/jcdm-framework/src/main/java/com/jcdm/framework/web/domain/server/SysFile.java
new file mode 100644
index 0000000..baba065
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/web/domain/server/SysFile.java
@@ -0,0 +1,114 @@
+package com.jcdm.framework.web.domain.server;
+
+/**
+ * 绯荤粺鏂囦欢鐩稿叧淇℃伅
+ * 
+ * @author jc
+ */
+public class SysFile
+{
+    /**
+     * 鐩樼璺緞
+     */
+    private String dirName;
+
+    /**
+     * 鐩樼绫诲瀷
+     */
+    private String sysTypeName;
+
+    /**
+     * 鏂囦欢绫诲瀷
+     */
+    private String typeName;
+
+    /**
+     * 鎬诲ぇ灏�
+     */
+    private String total;
+
+    /**
+     * 鍓╀綑澶у皬
+     */
+    private String free;
+
+    /**
+     * 宸茬粡浣跨敤閲�
+     */
+    private String used;
+
+    /**
+     * 璧勬簮鐨勪娇鐢ㄧ巼
+     */
+    private double usage;
+
+    public String getDirName()
+    {
+        return dirName;
+    }
+
+    public void setDirName(String dirName)
+    {
+        this.dirName = dirName;
+    }
+
+    public String getSysTypeName()
+    {
+        return sysTypeName;
+    }
+
+    public void setSysTypeName(String sysTypeName)
+    {
+        this.sysTypeName = sysTypeName;
+    }
+
+    public String getTypeName()
+    {
+        return typeName;
+    }
+
+    public void setTypeName(String typeName)
+    {
+        this.typeName = typeName;
+    }
+
+    public String getTotal()
+    {
+        return total;
+    }
+
+    public void setTotal(String total)
+    {
+        this.total = total;
+    }
+
+    public String getFree()
+    {
+        return free;
+    }
+
+    public void setFree(String free)
+    {
+        this.free = free;
+    }
+
+    public String getUsed()
+    {
+        return used;
+    }
+
+    public void setUsed(String used)
+    {
+        this.used = used;
+    }
+
+    public double getUsage()
+    {
+        return usage;
+    }
+
+    public void setUsage(double usage)
+    {
+        this.usage = usage;
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/web/exception/GlobalExceptionHandler.java b/jcdm-framework/src/main/java/com/jcdm/framework/web/exception/GlobalExceptionHandler.java
new file mode 100644
index 0000000..a97dcad
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/web/exception/GlobalExceptionHandler.java
@@ -0,0 +1,138 @@
+package com.jcdm.framework.web.exception;
+
+import javax.servlet.http.HttpServletRequest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.validation.BindException;
+import org.springframework.web.HttpRequestMethodNotSupportedException;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.MissingPathVariableException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
+import com.jcdm.common.constant.HttpStatus;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.exception.DemoModeException;
+import com.jcdm.common.exception.ServiceException;
+import com.jcdm.common.utils.StringUtils;
+
+/**
+ * 鍏ㄥ眬寮傚父澶勭悊鍣�
+ * 
+ * @author jc
+ */
+@RestControllerAdvice
+public class GlobalExceptionHandler
+{
+    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
+
+    /**
+     * 鏉冮檺鏍¢獙寮傚父
+     */
+    @ExceptionHandler(AccessDeniedException.class)
+    public AjaxResult handleAccessDeniedException(AccessDeniedException e, HttpServletRequest request)
+    {
+        String requestURI = request.getRequestURI();
+        log.error("璇锋眰鍦板潃'{}',鏉冮檺鏍¢獙澶辫触'{}'", requestURI, e.getMessage());
+        return AjaxResult.error(HttpStatus.FORBIDDEN, "娌℃湁鏉冮檺锛岃鑱旂郴绠$悊鍛樻巿鏉�");
+    }
+
+    /**
+     * 璇锋眰鏂瑰紡涓嶆敮鎸�
+     */
+    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
+    public AjaxResult handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e,
+            HttpServletRequest request)
+    {
+        String requestURI = request.getRequestURI();
+        log.error("璇锋眰鍦板潃'{}',涓嶆敮鎸�'{}'璇锋眰", requestURI, e.getMethod());
+        return AjaxResult.error(e.getMessage());
+    }
+
+    /**
+     * 涓氬姟寮傚父
+     */
+    @ExceptionHandler(ServiceException.class)
+    public AjaxResult handleServiceException(ServiceException e, HttpServletRequest request)
+    {
+        log.error(e.getMessage(), e);
+        Integer code = e.getCode();
+        return StringUtils.isNotNull(code) ? AjaxResult.error(code, e.getMessage()) : AjaxResult.error(e.getMessage());
+    }
+
+    /**
+     * 璇锋眰璺緞涓己灏戝繀闇�鐨勮矾寰勫彉閲�
+     */
+    @ExceptionHandler(MissingPathVariableException.class)
+    public AjaxResult handleMissingPathVariableException(MissingPathVariableException e, HttpServletRequest request)
+    {
+        String requestURI = request.getRequestURI();
+        log.error("璇锋眰璺緞涓己灏戝繀闇�鐨勮矾寰勫彉閲�'{}',鍙戠敓绯荤粺寮傚父.", requestURI, e);
+        return AjaxResult.error(String.format("璇锋眰璺緞涓己灏戝繀闇�鐨勮矾寰勫彉閲廩%s]", e.getVariableName()));
+    }
+
+    /**
+     * 璇锋眰鍙傛暟绫诲瀷涓嶅尮閰�
+     */
+    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
+    public AjaxResult handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e, HttpServletRequest request)
+    {
+        String requestURI = request.getRequestURI();
+        log.error("璇锋眰鍙傛暟绫诲瀷涓嶅尮閰�'{}',鍙戠敓绯荤粺寮傚父.", requestURI, e);
+        return AjaxResult.error(String.format("璇锋眰鍙傛暟绫诲瀷涓嶅尮閰嶏紝鍙傛暟[%s]瑕佹眰绫诲瀷涓猴細'%s'锛屼絾杈撳叆鍊间负锛�'%s'", e.getName(), e.getRequiredType().getName(), e.getValue()));
+    }
+
+    /**
+     * 鎷︽埅鏈煡鐨勮繍琛屾椂寮傚父
+     */
+    @ExceptionHandler(RuntimeException.class)
+    public AjaxResult handleRuntimeException(RuntimeException e, HttpServletRequest request)
+    {
+        String requestURI = request.getRequestURI();
+        log.error("璇锋眰鍦板潃'{}',鍙戠敓鏈煡寮傚父.", requestURI, e);
+        return AjaxResult.error(e.getMessage());
+    }
+
+    /**
+     * 绯荤粺寮傚父
+     */
+    @ExceptionHandler(Exception.class)
+    public AjaxResult handleException(Exception e, HttpServletRequest request)
+    {
+        String requestURI = request.getRequestURI();
+        log.error("璇锋眰鍦板潃'{}',鍙戠敓绯荤粺寮傚父.", requestURI, e);
+        return AjaxResult.error(e.getMessage());
+    }
+
+    /**
+     * 鑷畾涔夐獙璇佸紓甯�
+     */
+    @ExceptionHandler(BindException.class)
+    public AjaxResult handleBindException(BindException e)
+    {
+        log.error(e.getMessage(), e);
+        String message = e.getAllErrors().get(0).getDefaultMessage();
+        return AjaxResult.error(message);
+    }
+
+    /**
+     * 鑷畾涔夐獙璇佸紓甯�
+     */
+    @ExceptionHandler(MethodArgumentNotValidException.class)
+    public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e)
+    {
+        log.error(e.getMessage(), e);
+        String message = e.getBindingResult().getFieldError().getDefaultMessage();
+        return AjaxResult.error(message);
+    }
+
+    /**
+     * 婕旂ず妯″紡寮傚父
+     */
+    @ExceptionHandler(DemoModeException.class)
+    public AjaxResult handleDemoModeException(DemoModeException e)
+    {
+        return AjaxResult.error("婕旂ず妯″紡锛屼笉鍏佽鎿嶄綔");
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/web/service/PermissionService.java b/jcdm-framework/src/main/java/com/jcdm/framework/web/service/PermissionService.java
new file mode 100644
index 0000000..fd6d82e
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/web/service/PermissionService.java
@@ -0,0 +1,159 @@
+package com.jcdm.framework.web.service;
+
+import java.util.Set;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+import com.jcdm.common.constant.Constants;
+import com.jcdm.common.core.domain.entity.SysRole;
+import com.jcdm.common.core.domain.model.LoginUser;
+import com.jcdm.common.utils.SecurityUtils;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.framework.security.context.PermissionContextHolder;
+
+/**
+ * 鑷畾涔夋潈闄愬疄鐜帮紝ss鍙栬嚜SpringSecurity棣栧瓧姣�
+ * 
+ * @author jc
+ */
+@Service("ss")
+public class PermissionService
+{
+    /**
+     * 楠岃瘉鐢ㄦ埛鏄惁鍏峰鏌愭潈闄�
+     * 
+     * @param permission 鏉冮檺瀛楃涓�
+     * @return 鐢ㄦ埛鏄惁鍏峰鏌愭潈闄�
+     */
+    public boolean hasPermi(String permission)
+    {
+        if (StringUtils.isEmpty(permission))
+        {
+            return false;
+        }
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions()))
+        {
+            return false;
+        }
+        PermissionContextHolder.setContext(permission);
+        return hasPermissions(loginUser.getPermissions(), permission);
+    }
+
+    /**
+     * 楠岃瘉鐢ㄦ埛鏄惁涓嶅叿澶囨煇鏉冮檺锛屼笌 hasPermi閫昏緫鐩稿弽
+     *
+     * @param permission 鏉冮檺瀛楃涓�
+     * @return 鐢ㄦ埛鏄惁涓嶅叿澶囨煇鏉冮檺
+     */
+    public boolean lacksPermi(String permission)
+    {
+        return hasPermi(permission) != true;
+    }
+
+    /**
+     * 楠岃瘉鐢ㄦ埛鏄惁鍏锋湁浠ヤ笅浠绘剰涓�涓潈闄�
+     *
+     * @param permissions 浠� PERMISSION_DELIMETER 涓哄垎闅旂鐨勬潈闄愬垪琛�
+     * @return 鐢ㄦ埛鏄惁鍏锋湁浠ヤ笅浠绘剰涓�涓潈闄�
+     */
+    public boolean hasAnyPermi(String permissions)
+    {
+        if (StringUtils.isEmpty(permissions))
+        {
+            return false;
+        }
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions()))
+        {
+            return false;
+        }
+        PermissionContextHolder.setContext(permissions);
+        Set<String> authorities = loginUser.getPermissions();
+        for (String permission : permissions.split(Constants.PERMISSION_DELIMETER))
+        {
+            if (permission != null && hasPermissions(authorities, permission))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 鍒ゆ柇鐢ㄦ埛鏄惁鎷ユ湁鏌愪釜瑙掕壊
+     * 
+     * @param role 瑙掕壊瀛楃涓�
+     * @return 鐢ㄦ埛鏄惁鍏峰鏌愯鑹�
+     */
+    public boolean hasRole(String role)
+    {
+        if (StringUtils.isEmpty(role))
+        {
+            return false;
+        }
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles()))
+        {
+            return false;
+        }
+        for (SysRole sysRole : loginUser.getUser().getRoles())
+        {
+            String roleKey = sysRole.getRoleKey();
+            if (Constants.SUPER_ADMIN.equals(roleKey) || roleKey.equals(StringUtils.trim(role)))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 楠岃瘉鐢ㄦ埛鏄惁涓嶅叿澶囨煇瑙掕壊锛屼笌 isRole閫昏緫鐩稿弽銆�
+     *
+     * @param role 瑙掕壊鍚嶇О
+     * @return 鐢ㄦ埛鏄惁涓嶅叿澶囨煇瑙掕壊
+     */
+    public boolean lacksRole(String role)
+    {
+        return hasRole(role) != true;
+    }
+
+    /**
+     * 楠岃瘉鐢ㄦ埛鏄惁鍏锋湁浠ヤ笅浠绘剰涓�涓鑹�
+     *
+     * @param roles 浠� ROLE_NAMES_DELIMETER 涓哄垎闅旂鐨勮鑹插垪琛�
+     * @return 鐢ㄦ埛鏄惁鍏锋湁浠ヤ笅浠绘剰涓�涓鑹�
+     */
+    public boolean hasAnyRoles(String roles)
+    {
+        if (StringUtils.isEmpty(roles))
+        {
+            return false;
+        }
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles()))
+        {
+            return false;
+        }
+        for (String role : roles.split(Constants.ROLE_DELIMETER))
+        {
+            if (hasRole(role))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 鍒ゆ柇鏄惁鍖呭惈鏉冮檺
+     * 
+     * @param permissions 鏉冮檺鍒楄〃
+     * @param permission 鏉冮檺瀛楃涓�
+     * @return 鐢ㄦ埛鏄惁鍏峰鏌愭潈闄�
+     */
+    private boolean hasPermissions(Set<String> permissions, String permission)
+    {
+        return permissions.contains(Constants.ALL_PERMISSION) || permissions.contains(StringUtils.trim(permission));
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/web/service/SysLoginService.java b/jcdm-framework/src/main/java/com/jcdm/framework/web/service/SysLoginService.java
new file mode 100644
index 0000000..2fe0c91
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/web/service/SysLoginService.java
@@ -0,0 +1,181 @@
+package com.jcdm.framework.web.service;
+
+import javax.annotation.Resource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.stereotype.Component;
+import com.jcdm.common.constant.CacheConstants;
+import com.jcdm.common.constant.Constants;
+import com.jcdm.common.constant.UserConstants;
+import com.jcdm.common.core.domain.entity.SysUser;
+import com.jcdm.common.core.domain.model.LoginUser;
+import com.jcdm.common.core.redis.RedisCache;
+import com.jcdm.common.exception.ServiceException;
+import com.jcdm.common.exception.user.BlackListException;
+import com.jcdm.common.exception.user.CaptchaException;
+import com.jcdm.common.exception.user.CaptchaExpireException;
+import com.jcdm.common.exception.user.UserNotExistsException;
+import com.jcdm.common.exception.user.UserPasswordNotMatchException;
+import com.jcdm.common.utils.DateUtils;
+import com.jcdm.common.utils.MessageUtils;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.common.utils.ip.IpUtils;
+import com.jcdm.framework.manager.AsyncManager;
+import com.jcdm.framework.manager.factory.AsyncFactory;
+import com.jcdm.framework.security.context.AuthenticationContextHolder;
+import com.jcdm.system.service.ISysConfigService;
+import com.jcdm.system.service.ISysUserService;
+
+/**
+ * 鐧诲綍鏍¢獙鏂规硶
+ * 
+ * @author jc
+ */
+@Component
+public class SysLoginService
+{
+    @Autowired
+    private TokenService tokenService;
+
+    @Resource
+    private AuthenticationManager authenticationManager;
+
+    @Autowired
+    private RedisCache redisCache;
+    
+    @Autowired
+    private ISysUserService userService;
+
+    @Autowired
+    private ISysConfigService configService;
+
+    /**
+     * 鐧诲綍楠岃瘉
+     * 
+     * @param username 鐢ㄦ埛鍚�
+     * @param password 瀵嗙爜
+     * @param code 楠岃瘉鐮�
+     * @param uuid 鍞竴鏍囪瘑
+     * @return 缁撴灉
+     */
+    public String login(String username, String password, String code, String uuid)
+    {
+        // 楠岃瘉鐮佹牎楠�
+        //validateCaptcha(username, code, uuid);
+        // 鐧诲綍鍓嶇疆鏍¢獙
+        loginPreCheck(username, password);
+        // 鐢ㄦ埛楠岃瘉
+        Authentication authentication = null;
+        try
+        {
+            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
+            AuthenticationContextHolder.setContext(authenticationToken);
+            // 璇ユ柟娉曚細鍘昏皟鐢║serDetailsServiceImpl.loadUserByUsername
+            authentication = authenticationManager.authenticate(authenticationToken);
+        }
+        catch (Exception e)
+        {
+            if (e instanceof BadCredentialsException)
+            {
+                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
+                throw new UserPasswordNotMatchException();
+            }
+            else
+            {
+                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));
+                throw new ServiceException(e.getMessage());
+            }
+        }
+        finally
+        {
+            AuthenticationContextHolder.clearContext();
+        }
+        AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
+        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
+        recordLoginInfo(loginUser.getUserId());
+        // 鐢熸垚token
+        return tokenService.createToken(loginUser);
+    }
+
+    /**
+     * 鏍¢獙楠岃瘉鐮�
+     * 
+     * @param username 鐢ㄦ埛鍚�
+     * @param code 楠岃瘉鐮�
+     * @param uuid 鍞竴鏍囪瘑
+     * @return 缁撴灉
+     */
+    public void validateCaptcha(String username, String code, String uuid)
+    {
+        boolean captchaEnabled = configService.selectCaptchaEnabled();
+        if (captchaEnabled)
+        {
+            String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, "");
+            String captcha = redisCache.getCacheObject(verifyKey);
+            redisCache.deleteObject(verifyKey);
+            if (captcha == null)
+            {
+                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")));
+                throw new CaptchaExpireException();
+            }
+            if (!code.equalsIgnoreCase(captcha))
+            {
+                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
+                throw new CaptchaException();
+            }
+        }
+    }
+
+    /**
+     * 鐧诲綍鍓嶇疆鏍¢獙
+     * @param username 鐢ㄦ埛鍚�
+     * @param password 鐢ㄦ埛瀵嗙爜
+     */
+    public void loginPreCheck(String username, String password)
+    {
+        // 鐢ㄦ埛鍚嶆垨瀵嗙爜涓虹┖ 閿欒
+        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password))
+        {
+            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null")));
+            throw new UserNotExistsException();
+        }
+        // 瀵嗙爜濡傛灉涓嶅湪鎸囧畾鑼冨洿鍐� 閿欒
+        if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
+                || password.length() > UserConstants.PASSWORD_MAX_LENGTH)
+        {
+            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
+            throw new UserPasswordNotMatchException();
+        }
+        // 鐢ㄦ埛鍚嶄笉鍦ㄦ寚瀹氳寖鍥村唴 閿欒
+        if (username.length() < UserConstants.USERNAME_MIN_LENGTH
+                || username.length() > UserConstants.USERNAME_MAX_LENGTH)
+        {
+            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
+            throw new UserPasswordNotMatchException();
+        }
+        // IP榛戝悕鍗曟牎楠�
+        String blackStr = configService.selectConfigByKey("sys.login.blackIPList");
+        if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr()))
+        {
+            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("login.blocked")));
+            throw new BlackListException();
+        }
+    }
+
+    /**
+     * 璁板綍鐧诲綍淇℃伅
+     *
+     * @param userId 鐢ㄦ埛ID
+     */
+    public void recordLoginInfo(Long userId)
+    {
+        SysUser sysUser = new SysUser();
+        sysUser.setUserId(userId);
+        sysUser.setLoginIp(IpUtils.getIpAddr());
+        sysUser.setLoginDate(DateUtils.getNowDate());
+        userService.updateUserProfile(sysUser);
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/web/service/SysPasswordService.java b/jcdm-framework/src/main/java/com/jcdm/framework/web/service/SysPasswordService.java
new file mode 100644
index 0000000..1d01e3d
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/web/service/SysPasswordService.java
@@ -0,0 +1,94 @@
+package com.jcdm.framework.web.service;
+
+import java.util.concurrent.TimeUnit;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.security.core.Authentication;
+import org.springframework.stereotype.Component;
+import com.jcdm.common.constant.CacheConstants;
+import com.jcdm.common.constant.Constants;
+import com.jcdm.common.core.domain.entity.SysUser;
+import com.jcdm.common.core.redis.RedisCache;
+import com.jcdm.common.exception.user.UserPasswordNotMatchException;
+import com.jcdm.common.exception.user.UserPasswordRetryLimitExceedException;
+import com.jcdm.common.utils.MessageUtils;
+import com.jcdm.common.utils.SecurityUtils;
+import com.jcdm.framework.manager.AsyncManager;
+import com.jcdm.framework.manager.factory.AsyncFactory;
+import com.jcdm.framework.security.context.AuthenticationContextHolder;
+
+/**
+ * 鐧诲綍瀵嗙爜鏂规硶
+ * 
+ * @author jc
+ */
+@Component
+public class SysPasswordService
+{
+    @Autowired
+    private RedisCache redisCache;
+
+    @Value(value = "${user.password.maxRetryCount}")
+    private int maxRetryCount;
+
+    @Value(value = "${user.password.lockTime}")
+    private int lockTime;
+
+    /**
+     * 鐧诲綍璐︽埛瀵嗙爜閿欒娆℃暟缂撳瓨閿悕
+     * 
+     * @param username 鐢ㄦ埛鍚�
+     * @return 缂撳瓨閿甼ey
+     */
+    private String getCacheKey(String username)
+    {
+        return CacheConstants.PWD_ERR_CNT_KEY + username;
+    }
+
+    public void validate(SysUser user)
+    {
+        Authentication usernamePasswordAuthenticationToken = AuthenticationContextHolder.getContext();
+        String username = usernamePasswordAuthenticationToken.getName();
+        String password = usernamePasswordAuthenticationToken.getCredentials().toString();
+
+        Integer retryCount = redisCache.getCacheObject(getCacheKey(username));
+
+        if (retryCount == null)
+        {
+            retryCount = 0;
+        }
+
+        if (retryCount >= Integer.valueOf(maxRetryCount).intValue())
+        {
+            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL,
+                    MessageUtils.message("user.password.retry.limit.exceed", maxRetryCount, lockTime)));
+            throw new UserPasswordRetryLimitExceedException(maxRetryCount, lockTime);
+        }
+
+        if (!matches(user, password))
+        {
+            retryCount = retryCount + 1;
+            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL,
+                    MessageUtils.message("user.password.retry.limit.count", retryCount)));
+            redisCache.setCacheObject(getCacheKey(username), retryCount, lockTime, TimeUnit.MINUTES);
+            throw new UserPasswordNotMatchException();
+        }
+        else
+        {
+            clearLoginRecordCache(username);
+        }
+    }
+
+    public boolean matches(SysUser user, String rawPassword)
+    {
+        return SecurityUtils.matchesPassword(rawPassword, user.getPassword());
+    }
+
+    public void clearLoginRecordCache(String loginName)
+    {
+        if (redisCache.hasKey(getCacheKey(loginName)))
+        {
+            redisCache.deleteObject(getCacheKey(loginName));
+        }
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/web/service/SysPermissionService.java b/jcdm-framework/src/main/java/com/jcdm/framework/web/service/SysPermissionService.java
new file mode 100644
index 0000000..e98e3f2
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/web/service/SysPermissionService.java
@@ -0,0 +1,83 @@
+package com.jcdm.framework.web.service;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+import com.jcdm.common.core.domain.entity.SysRole;
+import com.jcdm.common.core.domain.entity.SysUser;
+import com.jcdm.system.service.ISysMenuService;
+import com.jcdm.system.service.ISysRoleService;
+
+/**
+ * 鐢ㄦ埛鏉冮檺澶勭悊
+ * 
+ * @author jc
+ */
+@Component
+public class SysPermissionService
+{
+    @Autowired
+    private ISysRoleService roleService;
+
+    @Autowired
+    private ISysMenuService menuService;
+
+    /**
+     * 鑾峰彇瑙掕壊鏁版嵁鏉冮檺
+     * 
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 瑙掕壊鏉冮檺淇℃伅
+     */
+    public Set<String> getRolePermission(SysUser user)
+    {
+        Set<String> roles = new HashSet<String>();
+        // 绠$悊鍛樻嫢鏈夋墍鏈夋潈闄�
+        if (user.isAdmin())
+        {
+            roles.add("admin");
+        }
+        else
+        {
+            roles.addAll(roleService.selectRolePermissionByUserId(user.getUserId()));
+        }
+        return roles;
+    }
+
+    /**
+     * 鑾峰彇鑿滃崟鏁版嵁鏉冮檺
+     * 
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 鑿滃崟鏉冮檺淇℃伅
+     */
+    public Set<String> getMenuPermission(SysUser user)
+    {
+        Set<String> perms = new HashSet<String>();
+        // 绠$悊鍛樻嫢鏈夋墍鏈夋潈闄�
+        if (user.isAdmin())
+        {
+            perms.add("*:*:*");
+        }
+        else
+        {
+            List<SysRole> roles = user.getRoles();
+            if (!CollectionUtils.isEmpty(roles))
+            {
+                // 澶氳鑹茶缃畃ermissions灞炴�э紝浠ヤ究鏁版嵁鏉冮檺鍖归厤鏉冮檺
+                for (SysRole role : roles)
+                {
+                    Set<String> rolePerms = menuService.selectMenuPermsByRoleId(role.getRoleId());
+                    role.setPermissions(rolePerms);
+                    perms.addAll(rolePerms);
+                }
+            }
+            else
+            {
+                perms.addAll(menuService.selectMenuPermsByUserId(user.getUserId()));
+            }
+        }
+        return perms;
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/web/service/SysRegisterService.java b/jcdm-framework/src/main/java/com/jcdm/framework/web/service/SysRegisterService.java
new file mode 100644
index 0000000..bd0a5c2
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/web/service/SysRegisterService.java
@@ -0,0 +1,115 @@
+package com.jcdm.framework.web.service;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import com.jcdm.common.constant.CacheConstants;
+import com.jcdm.common.constant.Constants;
+import com.jcdm.common.constant.UserConstants;
+import com.jcdm.common.core.domain.entity.SysUser;
+import com.jcdm.common.core.domain.model.RegisterBody;
+import com.jcdm.common.core.redis.RedisCache;
+import com.jcdm.common.exception.user.CaptchaException;
+import com.jcdm.common.exception.user.CaptchaExpireException;
+import com.jcdm.common.utils.MessageUtils;
+import com.jcdm.common.utils.SecurityUtils;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.framework.manager.AsyncManager;
+import com.jcdm.framework.manager.factory.AsyncFactory;
+import com.jcdm.system.service.ISysConfigService;
+import com.jcdm.system.service.ISysUserService;
+
+/**
+ * 娉ㄥ唽鏍¢獙鏂规硶
+ * 
+ * @author jc
+ */
+@Component
+public class SysRegisterService
+{
+    @Autowired
+    private ISysUserService userService;
+
+    @Autowired
+    private ISysConfigService configService;
+
+    @Autowired
+    private RedisCache redisCache;
+
+    /**
+     * 娉ㄥ唽
+     */
+    public String register(RegisterBody registerBody)
+    {
+        String msg = "", username = registerBody.getUsername(), password = registerBody.getPassword();
+        SysUser sysUser = new SysUser();
+        sysUser.setUserName(username);
+
+        // 楠岃瘉鐮佸紑鍏�
+        boolean captchaEnabled = configService.selectCaptchaEnabled();
+        if (captchaEnabled)
+        {
+            validateCaptcha(username, registerBody.getCode(), registerBody.getUuid());
+        }
+
+        if (StringUtils.isEmpty(username))
+        {
+            msg = "鐢ㄦ埛鍚嶄笉鑳戒负绌�";
+        }
+        else if (StringUtils.isEmpty(password))
+        {
+            msg = "鐢ㄦ埛瀵嗙爜涓嶈兘涓虹┖";
+        }
+        else if (username.length() < UserConstants.USERNAME_MIN_LENGTH
+                || username.length() > UserConstants.USERNAME_MAX_LENGTH)
+        {
+            msg = "璐︽埛闀垮害蹇呴』鍦�2鍒�20涓瓧绗︿箣闂�";
+        }
+        else if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
+                || password.length() > UserConstants.PASSWORD_MAX_LENGTH)
+        {
+            msg = "瀵嗙爜闀垮害蹇呴』鍦�5鍒�20涓瓧绗︿箣闂�";
+        }
+        else if (!userService.checkUserNameUnique(sysUser))
+        {
+            msg = "淇濆瓨鐢ㄦ埛'" + username + "'澶辫触锛屾敞鍐岃处鍙峰凡瀛樺湪";
+        }
+        else
+        {
+            sysUser.setNickName(username);
+            sysUser.setPassword(SecurityUtils.encryptPassword(password));
+            boolean regFlag = userService.registerUser(sysUser);
+            if (!regFlag)
+            {
+                msg = "娉ㄥ唽澶辫触,璇疯仈绯荤郴缁熺鐞嗕汉鍛�";
+            }
+            else
+            {
+                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.register.success")));
+            }
+        }
+        return msg;
+    }
+
+    /**
+     * 鏍¢獙楠岃瘉鐮�
+     * 
+     * @param username 鐢ㄦ埛鍚�
+     * @param code 楠岃瘉鐮�
+     * @param uuid 鍞竴鏍囪瘑
+     * @return 缁撴灉
+     */
+    public void validateCaptcha(String username, String code, String uuid)
+    {
+        String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, "");
+        String captcha = redisCache.getCacheObject(verifyKey);
+        redisCache.deleteObject(verifyKey);
+        if (captcha == null)
+        {
+            throw new CaptchaExpireException();
+        }
+        if (!code.equalsIgnoreCase(captcha))
+        {
+            throw new CaptchaException();
+        }
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/web/service/TokenService.java b/jcdm-framework/src/main/java/com/jcdm/framework/web/service/TokenService.java
new file mode 100644
index 0000000..64c14de
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/web/service/TokenService.java
@@ -0,0 +1,231 @@
+package com.jcdm.framework.web.service;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import javax.servlet.http.HttpServletRequest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import com.jcdm.common.constant.CacheConstants;
+import com.jcdm.common.constant.Constants;
+import com.jcdm.common.core.domain.model.LoginUser;
+import com.jcdm.common.core.redis.RedisCache;
+import com.jcdm.common.utils.ServletUtils;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.common.utils.ip.AddressUtils;
+import com.jcdm.common.utils.ip.IpUtils;
+import com.jcdm.common.utils.uuid.IdUtils;
+import eu.bitwalker.useragentutils.UserAgent;
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+
+/**
+ * token楠岃瘉澶勭悊
+ *
+ * @author jc
+ */
+@Component
+public class TokenService
+{
+    private static final Logger log = LoggerFactory.getLogger(TokenService.class);
+
+    // 浠ょ墝鑷畾涔夋爣璇�
+    @Value("${token.header}")
+    private String header;
+
+    // 浠ょ墝绉橀挜
+    @Value("${token.secret}")
+    private String secret;
+
+    // 浠ょ墝鏈夋晥鏈燂紙榛樿30鍒嗛挓锛�
+    @Value("${token.expireTime}")
+    private int expireTime;
+
+    protected static final long MILLIS_SECOND = 1000;
+
+    protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND;
+
+    private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L;
+
+    @Autowired
+    private RedisCache redisCache;
+
+    /**
+     * 鑾峰彇鐢ㄦ埛韬唤淇℃伅
+     *
+     * @return 鐢ㄦ埛淇℃伅
+     */
+    public LoginUser getLoginUser(HttpServletRequest request)
+    {
+        // 鑾峰彇璇锋眰鎼哄甫鐨勪护鐗�
+        String token = getToken(request);
+        if (StringUtils.isNotEmpty(token))
+        {
+            try
+            {
+                Claims claims = parseToken(token);
+                // 瑙f瀽瀵瑰簲鐨勬潈闄愪互鍙婄敤鎴蜂俊鎭�
+                String uuid = (String) claims.get(Constants.LOGIN_USER_KEY);
+                String userKey = getTokenKey(uuid);
+                LoginUser user = redisCache.getCacheObject(userKey);
+                return user;
+            }
+            catch (Exception e)
+            {
+                log.error("鑾峰彇鐢ㄦ埛淇℃伅寮傚父'{}'", e.getMessage());
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 璁剧疆鐢ㄦ埛韬唤淇℃伅
+     */
+    public void setLoginUser(LoginUser loginUser)
+    {
+        if (StringUtils.isNotNull(loginUser) && StringUtils.isNotEmpty(loginUser.getToken()))
+        {
+            refreshToken(loginUser);
+        }
+    }
+
+    /**
+     * 鍒犻櫎鐢ㄦ埛韬唤淇℃伅
+     */
+    public void delLoginUser(String token)
+    {
+        if (StringUtils.isNotEmpty(token))
+        {
+            String userKey = getTokenKey(token);
+            redisCache.deleteObject(userKey);
+        }
+    }
+
+    /**
+     * 鍒涘缓浠ょ墝
+     *
+     * @param loginUser 鐢ㄦ埛淇℃伅
+     * @return 浠ょ墝
+     */
+    public String createToken(LoginUser loginUser)
+    {
+        String token = IdUtils.fastUUID();
+        loginUser.setToken(token);
+        setUserAgent(loginUser);
+        refreshToken(loginUser);
+
+        Map<String, Object> claims = new HashMap<>();
+        claims.put(Constants.LOGIN_USER_KEY, token);
+        return createToken(claims);
+    }
+
+    /**
+     * 楠岃瘉浠ょ墝鏈夋晥鏈燂紝鐩稿樊涓嶈冻20鍒嗛挓锛岃嚜鍔ㄥ埛鏂扮紦瀛�
+     *
+     * @param loginUser
+     * @return 浠ょ墝
+     */
+    public void verifyToken(LoginUser loginUser)
+    {
+        long expireTime = loginUser.getExpireTime();
+        long currentTime = System.currentTimeMillis();
+        if (expireTime - currentTime <= MILLIS_MINUTE_TEN)
+        {
+            refreshToken(loginUser);
+        }
+    }
+
+    /**
+     * 鍒锋柊浠ょ墝鏈夋晥鏈�
+     *
+     * @param loginUser 鐧诲綍淇℃伅
+     */
+    public void refreshToken(LoginUser loginUser)
+    {
+        loginUser.setLoginTime(System.currentTimeMillis());
+        loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE);
+        // 鏍规嵁uuid灏唋oginUser缂撳瓨
+        String userKey = getTokenKey(loginUser.getToken());
+        redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);
+    }
+
+    /**
+     * 璁剧疆鐢ㄦ埛浠g悊淇℃伅
+     *
+     * @param loginUser 鐧诲綍淇℃伅
+     */
+    public void setUserAgent(LoginUser loginUser)
+    {
+        UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
+        String ip = IpUtils.getIpAddr();
+        loginUser.setIpaddr(ip);
+        loginUser.setLoginLocation(AddressUtils.getRealAddressByIP(ip));
+        loginUser.setBrowser(userAgent.getBrowser().getName());
+        loginUser.setOs(userAgent.getOperatingSystem().getName());
+    }
+
+    /**
+     * 浠庢暟鎹0鏄庣敓鎴愪护鐗�
+     *
+     * @param claims 鏁版嵁澹版槑
+     * @return 浠ょ墝
+     */
+    private String createToken(Map<String, Object> claims)
+    {
+        String token = Jwts.builder()
+                .setClaims(claims)
+                .signWith(SignatureAlgorithm.HS512, secret).compact();
+        return token;
+    }
+
+    /**
+     * 浠庝护鐗屼腑鑾峰彇鏁版嵁澹版槑
+     *
+     * @param token 浠ょ墝
+     * @return 鏁版嵁澹版槑
+     */
+    private Claims parseToken(String token)
+    {
+        return Jwts.parser()
+                .setSigningKey(secret)
+                .parseClaimsJws(token)
+                .getBody();
+    }
+
+    /**
+     * 浠庝护鐗屼腑鑾峰彇鐢ㄦ埛鍚�
+     *
+     * @param token 浠ょ墝
+     * @return 鐢ㄦ埛鍚�
+     */
+    public String getUsernameFromToken(String token)
+    {
+        Claims claims = parseToken(token);
+        return claims.getSubject();
+    }
+
+    /**
+     * 鑾峰彇璇锋眰token
+     *
+     * @param request
+     * @return token
+     */
+    private String getToken(HttpServletRequest request)
+    {
+        String token = request.getHeader(header);
+        if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX))
+        {
+            token = token.replace(Constants.TOKEN_PREFIX, "");
+        }
+        return token;
+    }
+
+    private String getTokenKey(String uuid)
+    {
+        return CacheConstants.LOGIN_TOKEN_KEY + uuid;
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/web/service/UserDetailsServiceImpl.java b/jcdm-framework/src/main/java/com/jcdm/framework/web/service/UserDetailsServiceImpl.java
new file mode 100644
index 0000000..660c290
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/web/service/UserDetailsServiceImpl.java
@@ -0,0 +1,66 @@
+package com.jcdm.framework.web.service;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.stereotype.Service;
+import com.jcdm.common.core.domain.entity.SysUser;
+import com.jcdm.common.core.domain.model.LoginUser;
+import com.jcdm.common.enums.UserStatus;
+import com.jcdm.common.exception.ServiceException;
+import com.jcdm.common.utils.MessageUtils;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.system.service.ISysUserService;
+
+/**
+ * 鐢ㄦ埛楠岃瘉澶勭悊
+ *
+ * @author jc
+ */
+@Service
+public class UserDetailsServiceImpl implements UserDetailsService
+{
+    private static final Logger log = LoggerFactory.getLogger(UserDetailsServiceImpl.class);
+
+    @Autowired
+    private ISysUserService userService;
+    
+    @Autowired
+    private SysPasswordService passwordService;
+
+    @Autowired
+    private SysPermissionService permissionService;
+
+    @Override
+    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
+    {
+        SysUser user = userService.selectUserByUserName(username);
+        if (StringUtils.isNull(user))
+        {
+            log.info("鐧诲綍鐢ㄦ埛锛歿} 涓嶅瓨鍦�.", username);
+            throw new ServiceException(MessageUtils.message("user.not.exists"));
+        }
+        else if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
+        {
+            log.info("鐧诲綍鐢ㄦ埛锛歿} 宸茶鍒犻櫎.", username);
+            throw new ServiceException(MessageUtils.message("user.password.delete"));
+        }
+        else if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
+        {
+            log.info("鐧诲綍鐢ㄦ埛锛歿} 宸茶鍋滅敤.", username);
+            throw new ServiceException(MessageUtils.message("user.blocked"));
+        }
+
+        passwordService.validate(user);
+
+        return createLoginUser(user);
+    }
+
+    public UserDetails createLoginUser(SysUser user)
+    {
+        return new LoginUser(user.getUserId(), user.getDeptId(), user, permissionService.getMenuPermission(user));
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/websocket/PostController.java b/jcdm-framework/src/main/java/com/jcdm/framework/websocket/PostController.java
new file mode 100644
index 0000000..83126eb
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/websocket/PostController.java
@@ -0,0 +1,31 @@
+package com.jcdm.framework.websocket;
+
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.core.page.TableDataInfo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.websocket.Session;
+import javax.websocket.server.PathParam;
+import java.util.List;
+import java.util.Map;
+
+@RestController("/socketController")
+public class PostController {
+
+    @GetMapping("/postWebsocket")
+    public AjaxResult list(@PathParam("locationCode") String locationCode)
+    {
+        Map<String, Session> map = WebSocketUsers.getUsers();
+        //1銆佺洃鍚琸epserver鍦板潃 姣斿锛歄P.OP1010.START 銆丱P.OP1020.START 銆丱P.OP1030.START
+        //2銆佸綋鍏朵腑涓�涓偣浣嶅彂鐢熷彉鍖栨椂锛屽垽鏂鐐逛綅鏄摢涓�涓伐浣�
+        //
+        WebSocketUsers.sendMessageToUserByText(map.get(locationCode), "1");
+
+        return AjaxResult.success();
+    }
+
+
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/websocket/SemaphoreUtils.java b/jcdm-framework/src/main/java/com/jcdm/framework/websocket/SemaphoreUtils.java
new file mode 100644
index 0000000..56eecbd
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/websocket/SemaphoreUtils.java
@@ -0,0 +1,58 @@
+package com.jcdm.framework.websocket;
+
+import java.util.concurrent.Semaphore;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 淇″彿閲忕浉鍏冲鐞�
+ * 
+ * @author ruoyi
+ */
+public class SemaphoreUtils
+{
+    /**
+     * SemaphoreUtils 鏃ュ織鎺у埗鍣�
+     */
+    private static final Logger LOGGER = LoggerFactory.getLogger(SemaphoreUtils.class);
+
+    /**
+     * 鑾峰彇淇″彿閲�
+     * 
+     * @param semaphore
+     * @return
+     */
+    public static boolean tryAcquire(Semaphore semaphore)
+    {
+        boolean flag = false;
+
+        try
+        {
+            flag = semaphore.tryAcquire();
+        }
+        catch (Exception e)
+        {
+            LOGGER.error("鑾峰彇淇″彿閲忓紓甯�", e);
+        }
+
+        return flag;
+    }
+
+    /**
+     * 閲婃斁淇″彿閲�
+     * 
+     * @param semaphore
+     */
+    public static void release(Semaphore semaphore)
+    {
+
+        try
+        {
+            semaphore.release();
+        }
+        catch (Exception e)
+        {
+            LOGGER.error("閲婃斁淇″彿閲忓紓甯�", e);
+        }
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/websocket/WebSocketConfig.java b/jcdm-framework/src/main/java/com/jcdm/framework/websocket/WebSocketConfig.java
new file mode 100644
index 0000000..ab24e76
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/websocket/WebSocketConfig.java
@@ -0,0 +1,20 @@
+package com.jcdm.framework.websocket;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.socket.server.standard.ServerEndpointExporter;
+
+/**
+ * websocket 閰嶇疆
+ * 
+ * @author ruoyi
+ */
+@Configuration
+public class WebSocketConfig
+{
+    @Bean
+    public ServerEndpointExporter serverEndpointExporter()
+    {
+        return new ServerEndpointExporter();
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/websocket/WebSocketServer.java b/jcdm-framework/src/main/java/com/jcdm/framework/websocket/WebSocketServer.java
new file mode 100644
index 0000000..57921d7
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/websocket/WebSocketServer.java
@@ -0,0 +1,108 @@
+package com.jcdm.framework.websocket;
+
+import java.util.concurrent.Semaphore;
+import javax.websocket.OnClose;
+import javax.websocket.OnError;
+import javax.websocket.OnMessage;
+import javax.websocket.OnOpen;
+import javax.websocket.Session;
+import javax.websocket.server.PathParam;
+import javax.websocket.server.ServerEndpoint;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+/**
+ * websocket 娑堟伅澶勭悊
+ * 
+ * @author ruoyi
+ */
+@Component
+@ServerEndpoint("/websocket/message/{userId}")
+public class WebSocketServer
+{
+    /**
+     * WebSocketServer 鏃ュ織鎺у埗鍣�
+     */
+    private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketServer.class);
+
+    /**
+     * 榛樿鏈�澶氬厑璁稿悓鏃跺湪绾夸汉鏁�100
+     */
+    public static int socketMaxOnlineCount = 100;
+
+    private static Semaphore socketSemaphore = new Semaphore(socketMaxOnlineCount);
+
+    /**鎺ユ敹userId*/
+    private String userId="";
+
+    /**
+     * 杩炴帴寤虹珛鎴愬姛璋冪敤鐨勬柟娉�
+     */
+    @OnOpen
+    public void onOpen(Session session, @PathParam("userId") String userId) throws Exception
+    {
+        boolean semaphoreFlag = false;
+        // 灏濊瘯鑾峰彇淇″彿閲�
+        semaphoreFlag = SemaphoreUtils.tryAcquire(socketSemaphore);
+        if (!semaphoreFlag)
+        {
+            // 鏈幏鍙栧埌淇″彿閲�
+            LOGGER.error("\n 褰撳墠鍦ㄧ嚎浜烘暟瓒呰繃闄愬埗鏁�- {}", socketMaxOnlineCount);
+            WebSocketUsers.sendMessageToUserByText(session, "褰撳墠鍦ㄧ嚎浜烘暟瓒呰繃闄愬埗鏁帮細" + socketMaxOnlineCount);
+            session.close();
+        }
+        else
+        {
+            // 娣诲姞鐢ㄦ埛
+//            WebSocketUsers.put(session.getId(), session);
+            WebSocketUsers.put(userId, session);
+            LOGGER.info("\n 寤虹珛杩炴帴 - {}", session);
+            LOGGER.info("\n 褰撳墠浜烘暟 - {}", WebSocketUsers.getUsers().size());
+            WebSocketUsers.sendMessageToUserByText(session, "杩炴帴鎴愬姛");
+        }
+    }
+
+    /**
+     * 杩炴帴鍏抽棴鏃跺鐞�
+     */
+    @OnClose
+    public void onClose(Session session)
+    {
+        LOGGER.info("\n 鍏抽棴杩炴帴 - {}", session);
+        // 绉婚櫎鐢ㄦ埛
+        WebSocketUsers.remove(session.getId());
+        // 鑾峰彇鍒颁俊鍙烽噺鍒欓渶閲婃斁
+        SemaphoreUtils.release(socketSemaphore);
+    }
+
+    /**
+     * 鎶涘嚭寮傚父鏃跺鐞�
+     */
+    @OnError
+    public void onError(Session session, Throwable exception) throws Exception
+    {
+        if (session.isOpen())
+        {
+            // 鍏抽棴杩炴帴
+            session.close();
+        }
+        String sessionId = session.getId();
+        LOGGER.info("\n 杩炴帴寮傚父 - {}", sessionId);
+        LOGGER.info("\n 寮傚父淇℃伅 - {}", exception);
+        // 绉诲嚭鐢ㄦ埛
+        WebSocketUsers.remove(sessionId);
+        // 鑾峰彇鍒颁俊鍙烽噺鍒欓渶閲婃斁
+        SemaphoreUtils.release(socketSemaphore);
+    }
+
+    /**
+     * 鏈嶅姟鍣ㄦ帴鏀跺埌瀹㈡埛绔秷鎭椂璋冪敤鐨勬柟娉�
+     */
+    @OnMessage
+    public void onMessage(String message, Session session)
+    {
+        String msg = message.replace("浣�", "鎴�").replace("鍚�", "");
+//        WebSocketUsers.sendMessageToUserByText(session, msg);
+    }
+}
diff --git a/jcdm-framework/src/main/java/com/jcdm/framework/websocket/WebSocketUsers.java b/jcdm-framework/src/main/java/com/jcdm/framework/websocket/WebSocketUsers.java
new file mode 100644
index 0000000..db0c715
--- /dev/null
+++ b/jcdm-framework/src/main/java/com/jcdm/framework/websocket/WebSocketUsers.java
@@ -0,0 +1,140 @@
+package com.jcdm.framework.websocket;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import javax.websocket.Session;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * websocket 瀹㈡埛绔敤鎴烽泦
+ * 
+ * @author ruoyi
+ */
+public class WebSocketUsers
+{
+    /**
+     * WebSocketUsers 鏃ュ織鎺у埗鍣�
+     */
+    private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketUsers.class);
+
+    /**
+     * 鐢ㄦ埛闆�
+     */
+    private static Map<String, Session> USERS = new ConcurrentHashMap<String, Session>();
+
+    /**
+     * 瀛樺偍鐢ㄦ埛
+     *
+     * @param key 鍞竴閿�
+     * @param session 鐢ㄦ埛淇℃伅
+     */
+    public static void put(String key, Session session)
+    {
+        USERS.put(key, session);
+    }
+
+    /**
+     * 绉婚櫎鐢ㄦ埛
+     *
+     * @param session 鐢ㄦ埛淇℃伅
+     *
+     * @return 绉婚櫎缁撴灉
+     */
+    public static boolean remove(Session session)
+    {
+        String key = null;
+        boolean flag = USERS.containsValue(session);
+        if (flag)
+        {
+            Set<Map.Entry<String, Session>> entries = USERS.entrySet();
+            for (Map.Entry<String, Session> entry : entries)
+            {
+                Session value = entry.getValue();
+                if (value.equals(session))
+                {
+                    key = entry.getKey();
+                    break;
+                }
+            }
+        }
+        else
+        {
+            return true;
+        }
+        return remove(key);
+    }
+
+    /**
+     * 绉诲嚭鐢ㄦ埛
+     *
+     * @param key 閿�
+     */
+    public static boolean remove(String key)
+    {
+        LOGGER.info("\n 姝e湪绉诲嚭鐢ㄦ埛 - {}", key);
+        Session remove = USERS.remove(key);
+        if (remove != null)
+        {
+            boolean containsValue = USERS.containsValue(remove);
+            LOGGER.info("\n 绉诲嚭缁撴灉 - {}", containsValue ? "澶辫触" : "鎴愬姛");
+            return containsValue;
+        }
+        else
+        {
+            return true;
+        }
+    }
+
+    /**
+     * 鑾峰彇鍦ㄧ嚎鐢ㄦ埛鍒楄〃
+     *
+     * @return 杩斿洖鐢ㄦ埛闆嗗悎
+     */
+    public static Map<String, Session> getUsers()
+    {
+        return USERS;
+    }
+
+    /**
+     * 缇ゅ彂娑堟伅鏂囨湰娑堟伅
+     *
+     * @param message 娑堟伅鍐呭
+     */
+    public static void sendMessageToUsersByText(String message)
+    {
+        Collection<Session> values = USERS.values();
+        for (Session value : values)
+        {
+            sendMessageToUserByText(value, message);
+        }
+    }
+
+    /**
+     * 鍙戦�佹枃鏈秷鎭�
+     *
+     * @param userName 鑷繁鐨勭敤鎴峰悕
+     * @param message 娑堟伅鍐呭
+     */
+    public static void sendMessageToUserByText(Session session, String message)
+    {
+        if (session != null)
+        {
+            try
+            {
+                session.getBasicRemote().sendText(message);
+            }
+            catch (IOException e)
+            {
+                LOGGER.error("\n[鍙戦�佹秷鎭紓甯竇", e);
+            }
+        }
+        else
+        {
+            LOGGER.info("\n[浣犲凡绂荤嚎]");
+        }
+    }
+}
diff --git a/jcdm-generator/pom.xml b/jcdm-generator/pom.xml
new file mode 100644
index 0000000..97eb900
--- /dev/null
+++ b/jcdm-generator/pom.xml
@@ -0,0 +1,40 @@
+<?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">
+    <parent>
+        <artifactId>jcdm</artifactId>
+        <groupId>com.jcdm</groupId>
+        <version>3.8.6</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>jcdm-generator</artifactId>
+
+    <description>
+        generator浠g爜鐢熸垚
+    </description>
+
+    <dependencies>
+
+        <!--velocity浠g爜鐢熸垚浣跨敤妯℃澘 -->
+        <dependency>
+            <groupId>org.apache.velocity</groupId>
+            <artifactId>velocity-engine-core</artifactId>
+        </dependency>
+
+        <!-- collections宸ュ叿绫� -->
+        <dependency>
+            <groupId>commons-collections</groupId>
+            <artifactId>commons-collections</artifactId>
+        </dependency>
+
+        <!-- 閫氱敤宸ュ叿-->
+        <dependency>
+            <groupId>com.jcdm</groupId>
+            <artifactId>jcdm-common</artifactId>
+        </dependency>
+
+    </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/jcdm-generator/src/main/java/com/jcdm/generator/config/GenConfig.java b/jcdm-generator/src/main/java/com/jcdm/generator/config/GenConfig.java
new file mode 100644
index 0000000..6417f6b
--- /dev/null
+++ b/jcdm-generator/src/main/java/com/jcdm/generator/config/GenConfig.java
@@ -0,0 +1,73 @@
+package com.jcdm.generator.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.stereotype.Component;
+
+/**
+ * 璇诲彇浠g爜鐢熸垚鐩稿叧閰嶇疆
+ * 
+ * @author jc
+ */
+@Component
+@ConfigurationProperties(prefix = "gen")
+@PropertySource(value = { "classpath:generator.yml" })
+public class GenConfig
+{
+    /** 浣滆�� */
+    public static String author;
+
+    /** 鐢熸垚鍖呰矾寰� */
+    public static String packageName;
+
+    /** 鑷姩鍘婚櫎琛ㄥ墠缂�锛岄粯璁ゆ槸false */
+    public static boolean autoRemovePre;
+
+    /** 琛ㄥ墠缂�(绫诲悕涓嶄細鍖呭惈琛ㄥ墠缂�) */
+    public static String tablePrefix;
+
+    public static String getAuthor()
+    {
+        return author;
+    }
+
+    @Value("${author}")
+    public void setAuthor(String author)
+    {
+        GenConfig.author = author;
+    }
+
+    public static String getPackageName()
+    {
+        return packageName;
+    }
+
+    @Value("${packageName}")
+    public void setPackageName(String packageName)
+    {
+        GenConfig.packageName = packageName;
+    }
+
+    public static boolean getAutoRemovePre()
+    {
+        return autoRemovePre;
+    }
+
+    @Value("${autoRemovePre}")
+    public void setAutoRemovePre(boolean autoRemovePre)
+    {
+        GenConfig.autoRemovePre = autoRemovePre;
+    }
+
+    public static String getTablePrefix()
+    {
+        return tablePrefix;
+    }
+
+    @Value("${tablePrefix}")
+    public void setTablePrefix(String tablePrefix)
+    {
+        GenConfig.tablePrefix = tablePrefix;
+    }
+}
diff --git a/jcdm-generator/src/main/java/com/jcdm/generator/controller/GenController.java b/jcdm-generator/src/main/java/com/jcdm/generator/controller/GenController.java
new file mode 100644
index 0000000..3a8ab9b
--- /dev/null
+++ b/jcdm-generator/src/main/java/com/jcdm/generator/controller/GenController.java
@@ -0,0 +1,214 @@
+package com.jcdm.generator.controller;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.io.IOUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.core.page.TableDataInfo;
+import com.jcdm.common.core.text.Convert;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.generator.domain.GenTable;
+import com.jcdm.generator.domain.GenTableColumn;
+import com.jcdm.generator.service.IGenTableColumnService;
+import com.jcdm.generator.service.IGenTableService;
+
+/**
+ * 浠g爜鐢熸垚 鎿嶄綔澶勭悊
+ * 
+ * @author jc
+ */
+@RestController
+@RequestMapping("/tool/gen")
+public class GenController extends BaseController
+{
+    @Autowired
+    private IGenTableService genTableService;
+
+    @Autowired
+    private IGenTableColumnService genTableColumnService;
+
+    /**
+     * 鏌ヨ浠g爜鐢熸垚鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('tool:gen:list')")
+    @GetMapping("/list")
+    public TableDataInfo genList(GenTable genTable)
+    {
+        startPage();
+        List<GenTable> list = genTableService.selectGenTableList(genTable);
+        return getDataTable(list);
+    }
+
+    /**
+     * 淇敼浠g爜鐢熸垚涓氬姟
+     */
+    @PreAuthorize("@ss.hasPermi('tool:gen:query')")
+    @GetMapping(value = "/{tableId}")
+    public AjaxResult getInfo(@PathVariable Long tableId)
+    {
+        GenTable table = genTableService.selectGenTableById(tableId);
+        List<GenTable> tables = genTableService.selectGenTableAll();
+        List<GenTableColumn> list = genTableColumnService.selectGenTableColumnListByTableId(tableId);
+        Map<String, Object> map = new HashMap<String, Object>();
+        map.put("info", table);
+        map.put("rows", list);
+        map.put("tables", tables);
+        return success(map);
+    }
+
+    /**
+     * 鏌ヨ鏁版嵁搴撳垪琛�
+     */
+    @PreAuthorize("@ss.hasPermi('tool:gen:list')")
+    @GetMapping("/db/list")
+    public TableDataInfo dataList(GenTable genTable)
+    {
+        startPage();
+        List<GenTable> list = genTableService.selectDbTableList(genTable);
+        return getDataTable(list);
+    }
+
+    /**
+     * 鏌ヨ鏁版嵁琛ㄥ瓧娈靛垪琛�
+     */
+    @PreAuthorize("@ss.hasPermi('tool:gen:list')")
+    @GetMapping(value = "/column/{tableId}")
+    public TableDataInfo columnList(Long tableId)
+    {
+        TableDataInfo dataInfo = new TableDataInfo();
+        List<GenTableColumn> list = genTableColumnService.selectGenTableColumnListByTableId(tableId);
+        dataInfo.setRows(list);
+        dataInfo.setTotal(list.size());
+        return dataInfo;
+    }
+
+    /**
+     * 瀵煎叆琛ㄧ粨鏋勶紙淇濆瓨锛�
+     */
+    @PreAuthorize("@ss.hasPermi('tool:gen:import')")
+    @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.IMPORT)
+    @PostMapping("/importTable")
+    public AjaxResult importTableSave(String tables)
+    {
+        String[] tableNames = Convert.toStrArray(tables);
+        // 鏌ヨ琛ㄤ俊鎭�
+        List<GenTable> tableList = genTableService.selectDbTableListByNames(tableNames);
+        genTableService.importGenTable(tableList);
+        return success();
+    }
+
+    /**
+     * 淇敼淇濆瓨浠g爜鐢熸垚涓氬姟
+     */
+    @PreAuthorize("@ss.hasPermi('tool:gen:edit')")
+    @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult editSave(@Validated @RequestBody GenTable genTable)
+    {
+        genTableService.validateEdit(genTable);
+        genTableService.updateGenTable(genTable);
+        return success();
+    }
+
+    /**
+     * 鍒犻櫎浠g爜鐢熸垚
+     */
+    @PreAuthorize("@ss.hasPermi('tool:gen:remove')")
+    @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{tableIds}")
+    public AjaxResult remove(@PathVariable Long[] tableIds)
+    {
+        genTableService.deleteGenTableByIds(tableIds);
+        return success();
+    }
+
+    /**
+     * 棰勮浠g爜
+     */
+    @PreAuthorize("@ss.hasPermi('tool:gen:preview')")
+    @GetMapping("/preview/{tableId}")
+    public AjaxResult preview(@PathVariable("tableId") Long tableId) throws IOException
+    {
+        Map<String, String> dataMap = genTableService.previewCode(tableId);
+        return success(dataMap);
+    }
+
+    /**
+     * 鐢熸垚浠g爜锛堜笅杞芥柟寮忥級
+     */
+    @PreAuthorize("@ss.hasPermi('tool:gen:code')")
+    @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.GENCODE)
+    @GetMapping("/download/{tableName}")
+    public void download(HttpServletResponse response, @PathVariable("tableName") String tableName) throws IOException
+    {
+        byte[] data = genTableService.downloadCode(tableName);
+        genCode(response, data);
+    }
+
+    /**
+     * 鐢熸垚浠g爜锛堣嚜瀹氫箟璺緞锛�
+     */
+    @PreAuthorize("@ss.hasPermi('tool:gen:code')")
+    @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.GENCODE)
+    @GetMapping("/genCode/{tableName}")
+    public AjaxResult genCode(@PathVariable("tableName") String tableName)
+    {
+        genTableService.generatorCode(tableName);
+        return success();
+    }
+
+    /**
+     * 鍚屾鏁版嵁搴�
+     */
+    @PreAuthorize("@ss.hasPermi('tool:gen:edit')")
+    @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.UPDATE)
+    @GetMapping("/synchDb/{tableName}")
+    public AjaxResult synchDb(@PathVariable("tableName") String tableName)
+    {
+        genTableService.synchDb(tableName);
+        return success();
+    }
+
+    /**
+     * 鎵归噺鐢熸垚浠g爜
+     */
+    @PreAuthorize("@ss.hasPermi('tool:gen:code')")
+    @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.GENCODE)
+    @GetMapping("/batchGenCode")
+    public void batchGenCode(HttpServletResponse response, String tables) throws IOException
+    {
+        String[] tableNames = Convert.toStrArray(tables);
+        byte[] data = genTableService.downloadCode(tableNames);
+        genCode(response, data);
+    }
+
+    /**
+     * 鐢熸垚zip鏂囦欢
+     */
+    private void genCode(HttpServletResponse response, byte[] data) throws IOException
+    {
+        response.reset();
+        response.addHeader("Access-Control-Allow-Origin", "*");
+        response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
+        response.setHeader("Content-Disposition", "attachment; filename=\"JCDM.zip\"");
+        response.addHeader("Content-Length", "" + data.length);
+        response.setContentType("application/octet-stream; charset=UTF-8");
+        IOUtils.write(data, response.getOutputStream());
+    }
+}
\ No newline at end of file
diff --git a/jcdm-generator/src/main/java/com/jcdm/generator/domain/GenTable.java b/jcdm-generator/src/main/java/com/jcdm/generator/domain/GenTable.java
new file mode 100644
index 0000000..8639fc3
--- /dev/null
+++ b/jcdm-generator/src/main/java/com/jcdm/generator/domain/GenTable.java
@@ -0,0 +1,385 @@
+package com.jcdm.generator.domain;
+
+import java.util.List;
+import javax.validation.Valid;
+import javax.validation.constraints.NotBlank;
+import org.apache.commons.lang3.ArrayUtils;
+import com.jcdm.common.constant.GenConstants;
+import com.jcdm.common.core.domain.BaseEntity;
+import com.jcdm.common.utils.StringUtils;
+
+/**
+ * 涓氬姟琛� gen_table
+ * 
+ * @author jc
+ */
+public class GenTable extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 缂栧彿 */
+    private Long tableId;
+
+    /** 琛ㄥ悕绉� */
+    @NotBlank(message = "琛ㄥ悕绉颁笉鑳戒负绌�")
+    private String tableName;
+
+    /** 琛ㄦ弿杩� */
+    @NotBlank(message = "琛ㄦ弿杩颁笉鑳戒负绌�")
+    private String tableComment;
+
+    /** 鍏宠仈鐖惰〃鐨勮〃鍚� */
+    private String subTableName;
+
+    /** 鏈〃鍏宠仈鐖惰〃鐨勫閿悕 */
+    private String subTableFkName;
+
+    /** 瀹炰綋绫诲悕绉�(棣栧瓧姣嶅ぇ鍐�) */
+    @NotBlank(message = "瀹炰綋绫诲悕绉颁笉鑳戒负绌�")
+    private String className;
+
+    /** 浣跨敤鐨勬ā鏉匡紙crud鍗曡〃鎿嶄綔 tree鏍戣〃鎿嶄綔 sub涓诲瓙琛ㄦ搷浣滐級 */
+    private String tplCategory;
+
+    /** 鍓嶇绫诲瀷锛坋lement-ui妯$増 element-plus妯$増锛� */
+    private String tplWebType;
+
+    /** 鐢熸垚鍖呰矾寰� */
+    @NotBlank(message = "鐢熸垚鍖呰矾寰勪笉鑳戒负绌�")
+    private String packageName;
+
+    /** 鐢熸垚妯″潡鍚� */
+    @NotBlank(message = "鐢熸垚妯″潡鍚嶄笉鑳戒负绌�")
+    private String moduleName;
+
+    /** 鐢熸垚涓氬姟鍚� */
+    @NotBlank(message = "鐢熸垚涓氬姟鍚嶄笉鑳戒负绌�")
+    private String businessName;
+
+    /** 鐢熸垚鍔熻兘鍚� */
+    @NotBlank(message = "鐢熸垚鍔熻兘鍚嶄笉鑳戒负绌�")
+    private String functionName;
+
+    /** 鐢熸垚浣滆�� */
+    @NotBlank(message = "浣滆�呬笉鑳戒负绌�")
+    private String functionAuthor;
+
+    /** 鐢熸垚浠g爜鏂瑰紡锛�0zip鍘嬬缉鍖� 1鑷畾涔夎矾寰勶級 */
+    private String genType;
+
+    /** 鐢熸垚璺緞锛堜笉濉粯璁ら」鐩矾寰勶級 */
+    private String genPath;
+
+    /** 涓婚敭淇℃伅 */
+    private GenTableColumn pkColumn;
+
+    /** 瀛愯〃淇℃伅 */
+    private GenTable subTable;
+
+    /** 琛ㄥ垪淇℃伅 */
+    @Valid
+    private List<GenTableColumn> columns;
+
+    /** 鍏跺畠鐢熸垚閫夐」 */
+    private String options;
+
+    /** 鏍戠紪鐮佸瓧娈� */
+    private String treeCode;
+
+    /** 鏍戠埗缂栫爜瀛楁 */
+    private String treeParentCode;
+
+    /** 鏍戝悕绉板瓧娈� */
+    private String treeName;
+
+    /** 涓婄骇鑿滃崟ID瀛楁 */
+    private String parentMenuId;
+
+    /** 涓婄骇鑿滃崟鍚嶇О瀛楁 */
+    private String parentMenuName;
+
+    public Long getTableId()
+    {
+        return tableId;
+    }
+
+    public void setTableId(Long tableId)
+    {
+        this.tableId = tableId;
+    }
+
+    public String getTableName()
+    {
+        return tableName;
+    }
+
+    public void setTableName(String tableName)
+    {
+        this.tableName = tableName;
+    }
+
+    public String getTableComment()
+    {
+        return tableComment;
+    }
+
+    public void setTableComment(String tableComment)
+    {
+        this.tableComment = tableComment;
+    }
+
+    public String getSubTableName()
+    {
+        return subTableName;
+    }
+
+    public void setSubTableName(String subTableName)
+    {
+        this.subTableName = subTableName;
+    }
+
+    public String getSubTableFkName()
+    {
+        return subTableFkName;
+    }
+
+    public void setSubTableFkName(String subTableFkName)
+    {
+        this.subTableFkName = subTableFkName;
+    }
+
+    public String getClassName()
+    {
+        return className;
+    }
+
+    public void setClassName(String className)
+    {
+        this.className = className;
+    }
+
+    public String getTplCategory()
+    {
+        return tplCategory;
+    }
+
+    public void setTplCategory(String tplCategory)
+    {
+        this.tplCategory = tplCategory;
+    }
+
+    public String getTplWebType()
+    {
+        return tplWebType;
+    }
+
+    public void setTplWebType(String tplWebType)
+    {
+        this.tplWebType = tplWebType;
+    }
+
+    public String getPackageName()
+    {
+        return packageName;
+    }
+
+    public void setPackageName(String packageName)
+    {
+        this.packageName = packageName;
+    }
+
+    public String getModuleName()
+    {
+        return moduleName;
+    }
+
+    public void setModuleName(String moduleName)
+    {
+        this.moduleName = moduleName;
+    }
+
+    public String getBusinessName()
+    {
+        return businessName;
+    }
+
+    public void setBusinessName(String businessName)
+    {
+        this.businessName = businessName;
+    }
+
+    public String getFunctionName()
+    {
+        return functionName;
+    }
+
+    public void setFunctionName(String functionName)
+    {
+        this.functionName = functionName;
+    }
+
+    public String getFunctionAuthor()
+    {
+        return functionAuthor;
+    }
+
+    public void setFunctionAuthor(String functionAuthor)
+    {
+        this.functionAuthor = functionAuthor;
+    }
+
+    public String getGenType()
+    {
+        return genType;
+    }
+
+    public void setGenType(String genType)
+    {
+        this.genType = genType;
+    }
+
+    public String getGenPath()
+    {
+        return genPath;
+    }
+
+    public void setGenPath(String genPath)
+    {
+        this.genPath = genPath;
+    }
+
+    public GenTableColumn getPkColumn()
+    {
+        return pkColumn;
+    }
+
+    public void setPkColumn(GenTableColumn pkColumn)
+    {
+        this.pkColumn = pkColumn;
+    }
+
+    public GenTable getSubTable()
+    {
+        return subTable;
+    }
+
+    public void setSubTable(GenTable subTable)
+    {
+        this.subTable = subTable;
+    }
+
+    public List<GenTableColumn> getColumns()
+    {
+        return columns;
+    }
+
+    public void setColumns(List<GenTableColumn> columns)
+    {
+        this.columns = columns;
+    }
+
+    public String getOptions()
+    {
+        return options;
+    }
+
+    public void setOptions(String options)
+    {
+        this.options = options;
+    }
+
+    public String getTreeCode()
+    {
+        return treeCode;
+    }
+
+    public void setTreeCode(String treeCode)
+    {
+        this.treeCode = treeCode;
+    }
+
+    public String getTreeParentCode()
+    {
+        return treeParentCode;
+    }
+
+    public void setTreeParentCode(String treeParentCode)
+    {
+        this.treeParentCode = treeParentCode;
+    }
+
+    public String getTreeName()
+    {
+        return treeName;
+    }
+
+    public void setTreeName(String treeName)
+    {
+        this.treeName = treeName;
+    }
+
+    public String getParentMenuId()
+    {
+        return parentMenuId;
+    }
+
+    public void setParentMenuId(String parentMenuId)
+    {
+        this.parentMenuId = parentMenuId;
+    }
+
+    public String getParentMenuName()
+    {
+        return parentMenuName;
+    }
+
+    public void setParentMenuName(String parentMenuName)
+    {
+        this.parentMenuName = parentMenuName;
+    }
+
+    public boolean isSub()
+    {
+        return isSub(this.tplCategory);
+    }
+
+    public static boolean isSub(String tplCategory)
+    {
+        return tplCategory != null && StringUtils.equals(GenConstants.TPL_SUB, tplCategory);
+    }
+
+    public boolean isTree()
+    {
+        return isTree(this.tplCategory);
+    }
+
+    public static boolean isTree(String tplCategory)
+    {
+        return tplCategory != null && StringUtils.equals(GenConstants.TPL_TREE, tplCategory);
+    }
+
+    public boolean isCrud()
+    {
+        return isCrud(this.tplCategory);
+    }
+
+    public static boolean isCrud(String tplCategory)
+    {
+        return tplCategory != null && StringUtils.equals(GenConstants.TPL_CRUD, tplCategory);
+    }
+
+    public boolean isSuperColumn(String javaField)
+    {
+        return isSuperColumn(this.tplCategory, javaField);
+    }
+
+    public static boolean isSuperColumn(String tplCategory, String javaField)
+    {
+        if (isTree(tplCategory))
+        {
+            return StringUtils.equalsAnyIgnoreCase(javaField,
+                    ArrayUtils.addAll(GenConstants.TREE_ENTITY, GenConstants.BASE_ENTITY));
+        }
+        return StringUtils.equalsAnyIgnoreCase(javaField, GenConstants.BASE_ENTITY);
+    }
+}
\ No newline at end of file
diff --git a/jcdm-generator/src/main/java/com/jcdm/generator/domain/GenTableColumn.java b/jcdm-generator/src/main/java/com/jcdm/generator/domain/GenTableColumn.java
new file mode 100644
index 0000000..bcd514c
--- /dev/null
+++ b/jcdm-generator/src/main/java/com/jcdm/generator/domain/GenTableColumn.java
@@ -0,0 +1,373 @@
+package com.jcdm.generator.domain;
+
+import javax.validation.constraints.NotBlank;
+import com.jcdm.common.core.domain.BaseEntity;
+import com.jcdm.common.utils.StringUtils;
+
+/**
+ * 浠g爜鐢熸垚涓氬姟瀛楁琛� gen_table_column
+ * 
+ * @author jc
+ */
+public class GenTableColumn extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 缂栧彿 */
+    private Long columnId;
+
+    /** 褰掑睘琛ㄧ紪鍙� */
+    private Long tableId;
+
+    /** 鍒楀悕绉� */
+    private String columnName;
+
+    /** 鍒楁弿杩� */
+    private String columnComment;
+
+    /** 鍒楃被鍨� */
+    private String columnType;
+
+    /** JAVA绫诲瀷 */
+    private String javaType;
+
+    /** JAVA瀛楁鍚� */
+    @NotBlank(message = "Java灞炴�т笉鑳戒负绌�")
+    private String javaField;
+
+    /** 鏄惁涓婚敭锛�1鏄級 */
+    private String isPk;
+
+    /** 鏄惁鑷锛�1鏄級 */
+    private String isIncrement;
+
+    /** 鏄惁蹇呭~锛�1鏄級 */
+    private String isRequired;
+
+    /** 鏄惁涓烘彃鍏ュ瓧娈碉紙1鏄級 */
+    private String isInsert;
+
+    /** 鏄惁缂栬緫瀛楁锛�1鏄級 */
+    private String isEdit;
+
+    /** 鏄惁鍒楄〃瀛楁锛�1鏄級 */
+    private String isList;
+
+    /** 鏄惁鏌ヨ瀛楁锛�1鏄級 */
+    private String isQuery;
+
+    /** 鏌ヨ鏂瑰紡锛圗Q绛変簬銆丯E涓嶇瓑浜庛�丟T澶т簬銆丩T灏忎簬銆丩IKE妯$硦銆丅ETWEEN鑼冨洿锛� */
+    private String queryType;
+
+    /** 鏄剧ず绫诲瀷锛坕nput鏂囨湰妗嗐�乼extarea鏂囨湰鍩熴�乻elect涓嬫媺妗嗐�乧heckbox澶嶉�夋銆乺adio鍗曢�夋銆乨atetime鏃ユ湡鎺т欢銆乮mage鍥剧墖涓婁紶鎺т欢銆乽pload鏂囦欢涓婁紶鎺т欢銆乪ditor瀵屾枃鏈帶浠讹級 */
+    private String htmlType;
+
+    /** 瀛楀吀绫诲瀷 */
+    private String dictType;
+
+    /** 鎺掑簭 */
+    private Integer sort;
+
+    public void setColumnId(Long columnId)
+    {
+        this.columnId = columnId;
+    }
+
+    public Long getColumnId()
+    {
+        return columnId;
+    }
+
+    public void setTableId(Long tableId)
+    {
+        this.tableId = tableId;
+    }
+
+    public Long getTableId()
+    {
+        return tableId;
+    }
+
+    public void setColumnName(String columnName)
+    {
+        this.columnName = columnName;
+    }
+
+    public String getColumnName()
+    {
+        return columnName;
+    }
+
+    public void setColumnComment(String columnComment)
+    {
+        this.columnComment = columnComment;
+    }
+
+    public String getColumnComment()
+    {
+        return columnComment;
+    }
+
+    public void setColumnType(String columnType)
+    {
+        this.columnType = columnType;
+    }
+
+    public String getColumnType()
+    {
+        return columnType;
+    }
+
+    public void setJavaType(String javaType)
+    {
+        this.javaType = javaType;
+    }
+
+    public String getJavaType()
+    {
+        return javaType;
+    }
+
+    public void setJavaField(String javaField)
+    {
+        this.javaField = javaField;
+    }
+
+    public String getJavaField()
+    {
+        return javaField;
+    }
+
+    public String getCapJavaField()
+    {
+        return StringUtils.capitalize(javaField);
+    }
+
+    public void setIsPk(String isPk)
+    {
+        this.isPk = isPk;
+    }
+
+    public String getIsPk()
+    {
+        return isPk;
+    }
+
+    public boolean isPk()
+    {
+        return isPk(this.isPk);
+    }
+
+    public boolean isPk(String isPk)
+    {
+        return isPk != null && StringUtils.equals("1", isPk);
+    }
+
+    public String getIsIncrement()
+    {
+        return isIncrement;
+    }
+
+    public void setIsIncrement(String isIncrement)
+    {
+        this.isIncrement = isIncrement;
+    }
+
+    public boolean isIncrement()
+    {
+        return isIncrement(this.isIncrement);
+    }
+
+    public boolean isIncrement(String isIncrement)
+    {
+        return isIncrement != null && StringUtils.equals("1", isIncrement);
+    }
+
+    public void setIsRequired(String isRequired)
+    {
+        this.isRequired = isRequired;
+    }
+
+    public String getIsRequired()
+    {
+        return isRequired;
+    }
+
+    public boolean isRequired()
+    {
+        return isRequired(this.isRequired);
+    }
+
+    public boolean isRequired(String isRequired)
+    {
+        return isRequired != null && StringUtils.equals("1", isRequired);
+    }
+
+    public void setIsInsert(String isInsert)
+    {
+        this.isInsert = isInsert;
+    }
+
+    public String getIsInsert()
+    {
+        return isInsert;
+    }
+
+    public boolean isInsert()
+    {
+        return isInsert(this.isInsert);
+    }
+
+    public boolean isInsert(String isInsert)
+    {
+        return isInsert != null && StringUtils.equals("1", isInsert);
+    }
+
+    public void setIsEdit(String isEdit)
+    {
+        this.isEdit = isEdit;
+    }
+
+    public String getIsEdit()
+    {
+        return isEdit;
+    }
+
+    public boolean isEdit()
+    {
+        return isInsert(this.isEdit);
+    }
+
+    public boolean isEdit(String isEdit)
+    {
+        return isEdit != null && StringUtils.equals("1", isEdit);
+    }
+
+    public void setIsList(String isList)
+    {
+        this.isList = isList;
+    }
+
+    public String getIsList()
+    {
+        return isList;
+    }
+
+    public boolean isList()
+    {
+        return isList(this.isList);
+    }
+
+    public boolean isList(String isList)
+    {
+        return isList != null && StringUtils.equals("1", isList);
+    }
+
+    public void setIsQuery(String isQuery)
+    {
+        this.isQuery = isQuery;
+    }
+
+    public String getIsQuery()
+    {
+        return isQuery;
+    }
+
+    public boolean isQuery()
+    {
+        return isQuery(this.isQuery);
+    }
+
+    public boolean isQuery(String isQuery)
+    {
+        return isQuery != null && StringUtils.equals("1", isQuery);
+    }
+
+    public void setQueryType(String queryType)
+    {
+        this.queryType = queryType;
+    }
+
+    public String getQueryType()
+    {
+        return queryType;
+    }
+
+    public String getHtmlType()
+    {
+        return htmlType;
+    }
+
+    public void setHtmlType(String htmlType)
+    {
+        this.htmlType = htmlType;
+    }
+
+    public void setDictType(String dictType)
+    {
+        this.dictType = dictType;
+    }
+
+    public String getDictType()
+    {
+        return dictType;
+    }
+
+    public void setSort(Integer sort)
+    {
+        this.sort = sort;
+    }
+
+    public Integer getSort()
+    {
+        return sort;
+    }
+
+    public boolean isSuperColumn()
+    {
+        return isSuperColumn(this.javaField);
+    }
+
+    public static boolean isSuperColumn(String javaField)
+    {
+        return StringUtils.equalsAnyIgnoreCase(javaField,
+                // BaseEntity
+                "createBy", "createTime", "updateBy", "updateTime", "remark",
+                // TreeEntity
+                "parentName", "parentId", "orderNum", "ancestors");
+    }
+
+    public boolean isUsableColumn()
+    {
+        return isUsableColumn(javaField);
+    }
+
+    public static boolean isUsableColumn(String javaField)
+    {
+        // isSuperColumn()涓殑鍚嶅崟鐢ㄤ簬閬垮厤鐢熸垚澶氫綑Domain灞炴�э紝鑻ユ煇浜涘睘鎬у湪鐢熸垚椤甸潰鏃堕渶瑕佺敤鍒颁笉鑳藉拷鐣ワ紝鍒欐斁鍦ㄦ澶勭櫧鍚嶅崟
+        return StringUtils.equalsAnyIgnoreCase(javaField, "parentId", "orderNum", "remark");
+    }
+
+    public String readConverterExp()
+    {
+        String remarks = StringUtils.substringBetween(this.columnComment, "锛�", "锛�");
+        StringBuffer sb = new StringBuffer();
+        if (StringUtils.isNotEmpty(remarks))
+        {
+            for (String value : remarks.split(" "))
+            {
+                if (StringUtils.isNotEmpty(value))
+                {
+                    Object startStr = value.subSequence(0, 1);
+                    String endStr = value.substring(1);
+                    sb.append("").append(startStr).append("=").append(endStr).append(",");
+                }
+            }
+            return sb.deleteCharAt(sb.length() - 1).toString();
+        }
+        else
+        {
+            return this.columnComment;
+        }
+    }
+}
diff --git a/jcdm-generator/src/main/java/com/jcdm/generator/mapper/GenTableColumnMapper.java b/jcdm-generator/src/main/java/com/jcdm/generator/mapper/GenTableColumnMapper.java
new file mode 100644
index 0000000..ffeed0c
--- /dev/null
+++ b/jcdm-generator/src/main/java/com/jcdm/generator/mapper/GenTableColumnMapper.java
@@ -0,0 +1,60 @@
+package com.jcdm.generator.mapper;
+
+import java.util.List;
+import com.jcdm.generator.domain.GenTableColumn;
+
+/**
+ * 涓氬姟瀛楁 鏁版嵁灞�
+ * 
+ * @author jc
+ */
+public interface GenTableColumnMapper
+{
+    /**
+     * 鏍规嵁琛ㄥ悕绉版煡璇㈠垪淇℃伅
+     * 
+     * @param tableName 琛ㄥ悕绉�
+     * @return 鍒椾俊鎭�
+     */
+    public List<GenTableColumn> selectDbTableColumnsByName(String tableName);
+
+    /**
+     * 鏌ヨ涓氬姟瀛楁鍒楄〃
+     * 
+     * @param tableId 涓氬姟瀛楁缂栧彿
+     * @return 涓氬姟瀛楁闆嗗悎
+     */
+    public List<GenTableColumn> selectGenTableColumnListByTableId(Long tableId);
+
+    /**
+     * 鏂板涓氬姟瀛楁
+     * 
+     * @param genTableColumn 涓氬姟瀛楁淇℃伅
+     * @return 缁撴灉
+     */
+    public int insertGenTableColumn(GenTableColumn genTableColumn);
+
+    /**
+     * 淇敼涓氬姟瀛楁
+     * 
+     * @param genTableColumn 涓氬姟瀛楁淇℃伅
+     * @return 缁撴灉
+     */
+    public int updateGenTableColumn(GenTableColumn genTableColumn);
+
+    /**
+     * 鍒犻櫎涓氬姟瀛楁
+     * 
+     * @param genTableColumns 鍒楁暟鎹�
+     * @return 缁撴灉
+     */
+    public int deleteGenTableColumns(List<GenTableColumn> genTableColumns);
+
+    /**
+     * 鎵归噺鍒犻櫎涓氬姟瀛楁
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁ID
+     * @return 缁撴灉
+     */
+    public int deleteGenTableColumnByIds(Long[] ids);
+}
diff --git a/jcdm-generator/src/main/java/com/jcdm/generator/mapper/GenTableMapper.java b/jcdm-generator/src/main/java/com/jcdm/generator/mapper/GenTableMapper.java
new file mode 100644
index 0000000..7003ed0
--- /dev/null
+++ b/jcdm-generator/src/main/java/com/jcdm/generator/mapper/GenTableMapper.java
@@ -0,0 +1,83 @@
+package com.jcdm.generator.mapper;
+
+import java.util.List;
+import com.jcdm.generator.domain.GenTable;
+
+/**
+ * 涓氬姟 鏁版嵁灞�
+ * 
+ * @author jc
+ */
+public interface GenTableMapper
+{
+    /**
+     * 鏌ヨ涓氬姟鍒楄〃
+     * 
+     * @param genTable 涓氬姟淇℃伅
+     * @return 涓氬姟闆嗗悎
+     */
+    public List<GenTable> selectGenTableList(GenTable genTable);
+
+    /**
+     * 鏌ヨ鎹簱鍒楄〃
+     * 
+     * @param genTable 涓氬姟淇℃伅
+     * @return 鏁版嵁搴撹〃闆嗗悎
+     */
+    public List<GenTable> selectDbTableList(GenTable genTable);
+
+    /**
+     * 鏌ヨ鎹簱鍒楄〃
+     * 
+     * @param tableNames 琛ㄥ悕绉扮粍
+     * @return 鏁版嵁搴撹〃闆嗗悎
+     */
+    public List<GenTable> selectDbTableListByNames(String[] tableNames);
+
+    /**
+     * 鏌ヨ鎵�鏈夎〃淇℃伅
+     * 
+     * @return 琛ㄤ俊鎭泦鍚�
+     */
+    public List<GenTable> selectGenTableAll();
+
+    /**
+     * 鏌ヨ琛↖D涓氬姟淇℃伅
+     * 
+     * @param id 涓氬姟ID
+     * @return 涓氬姟淇℃伅
+     */
+    public GenTable selectGenTableById(Long id);
+
+    /**
+     * 鏌ヨ琛ㄥ悕绉颁笟鍔′俊鎭�
+     * 
+     * @param tableName 琛ㄥ悕绉�
+     * @return 涓氬姟淇℃伅
+     */
+    public GenTable selectGenTableByName(String tableName);
+
+    /**
+     * 鏂板涓氬姟
+     * 
+     * @param genTable 涓氬姟淇℃伅
+     * @return 缁撴灉
+     */
+    public int insertGenTable(GenTable genTable);
+
+    /**
+     * 淇敼涓氬姟
+     * 
+     * @param genTable 涓氬姟淇℃伅
+     * @return 缁撴灉
+     */
+    public int updateGenTable(GenTable genTable);
+
+    /**
+     * 鎵归噺鍒犻櫎涓氬姟
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁ID
+     * @return 缁撴灉
+     */
+    public int deleteGenTableByIds(Long[] ids);
+}
diff --git a/jcdm-generator/src/main/java/com/jcdm/generator/service/GenTableColumnServiceImpl.java b/jcdm-generator/src/main/java/com/jcdm/generator/service/GenTableColumnServiceImpl.java
new file mode 100644
index 0000000..04937d4
--- /dev/null
+++ b/jcdm-generator/src/main/java/com/jcdm/generator/service/GenTableColumnServiceImpl.java
@@ -0,0 +1,68 @@
+package com.jcdm.generator.service;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.jcdm.common.core.text.Convert;
+import com.jcdm.generator.domain.GenTableColumn;
+import com.jcdm.generator.mapper.GenTableColumnMapper;
+
+/**
+ * 涓氬姟瀛楁 鏈嶅姟灞傚疄鐜�
+ * 
+ * @author jc
+ */
+@Service
+public class GenTableColumnServiceImpl implements IGenTableColumnService 
+{
+	@Autowired
+	private GenTableColumnMapper genTableColumnMapper;
+
+	/**
+     * 鏌ヨ涓氬姟瀛楁鍒楄〃
+     * 
+     * @param tableId 涓氬姟瀛楁缂栧彿
+     * @return 涓氬姟瀛楁闆嗗悎
+     */
+	@Override
+	public List<GenTableColumn> selectGenTableColumnListByTableId(Long tableId)
+	{
+	    return genTableColumnMapper.selectGenTableColumnListByTableId(tableId);
+	}
+	
+    /**
+     * 鏂板涓氬姟瀛楁
+     * 
+     * @param genTableColumn 涓氬姟瀛楁淇℃伅
+     * @return 缁撴灉
+     */
+	@Override
+	public int insertGenTableColumn(GenTableColumn genTableColumn)
+	{
+	    return genTableColumnMapper.insertGenTableColumn(genTableColumn);
+	}
+	
+	/**
+     * 淇敼涓氬姟瀛楁
+     * 
+     * @param genTableColumn 涓氬姟瀛楁淇℃伅
+     * @return 缁撴灉
+     */
+	@Override
+	public int updateGenTableColumn(GenTableColumn genTableColumn)
+	{
+	    return genTableColumnMapper.updateGenTableColumn(genTableColumn);
+	}
+
+	/**
+     * 鍒犻櫎涓氬姟瀛楁瀵硅薄
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁ID
+     * @return 缁撴灉
+     */
+	@Override
+	public int deleteGenTableColumnByIds(String ids)
+	{
+		return genTableColumnMapper.deleteGenTableColumnByIds(Convert.toLongArray(ids));
+	}
+}
diff --git a/jcdm-generator/src/main/java/com/jcdm/generator/service/GenTableServiceImpl.java b/jcdm-generator/src/main/java/com/jcdm/generator/service/GenTableServiceImpl.java
new file mode 100644
index 0000000..b35b284
--- /dev/null
+++ b/jcdm-generator/src/main/java/com/jcdm/generator/service/GenTableServiceImpl.java
@@ -0,0 +1,521 @@
+package com.jcdm.generator.service;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.Velocity;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import com.jcdm.common.constant.Constants;
+import com.jcdm.common.constant.GenConstants;
+import com.jcdm.common.core.text.CharsetKit;
+import com.jcdm.common.exception.ServiceException;
+import com.jcdm.common.utils.SecurityUtils;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.generator.domain.GenTable;
+import com.jcdm.generator.domain.GenTableColumn;
+import com.jcdm.generator.mapper.GenTableColumnMapper;
+import com.jcdm.generator.mapper.GenTableMapper;
+import com.jcdm.generator.util.GenUtils;
+import com.jcdm.generator.util.VelocityInitializer;
+import com.jcdm.generator.util.VelocityUtils;
+
+/**
+ * 涓氬姟 鏈嶅姟灞傚疄鐜�
+ * 
+ * @author jc
+ */
+@Service
+public class GenTableServiceImpl implements IGenTableService
+{
+    private static final Logger log = LoggerFactory.getLogger(GenTableServiceImpl.class);
+
+    @Autowired
+    private GenTableMapper genTableMapper;
+
+    @Autowired
+    private GenTableColumnMapper genTableColumnMapper;
+
+    /**
+     * 鏌ヨ涓氬姟淇℃伅
+     * 
+     * @param id 涓氬姟ID
+     * @return 涓氬姟淇℃伅
+     */
+    @Override
+    public GenTable selectGenTableById(Long id)
+    {
+        GenTable genTable = genTableMapper.selectGenTableById(id);
+        setTableFromOptions(genTable);
+        return genTable;
+    }
+
+    /**
+     * 鏌ヨ涓氬姟鍒楄〃
+     * 
+     * @param genTable 涓氬姟淇℃伅
+     * @return 涓氬姟闆嗗悎
+     */
+    @Override
+    public List<GenTable> selectGenTableList(GenTable genTable)
+    {
+        return genTableMapper.selectGenTableList(genTable);
+    }
+
+    /**
+     * 鏌ヨ鎹簱鍒楄〃
+     * 
+     * @param genTable 涓氬姟淇℃伅
+     * @return 鏁版嵁搴撹〃闆嗗悎
+     */
+    @Override
+    public List<GenTable> selectDbTableList(GenTable genTable)
+    {
+        return genTableMapper.selectDbTableList(genTable);
+    }
+
+    /**
+     * 鏌ヨ鎹簱鍒楄〃
+     * 
+     * @param tableNames 琛ㄥ悕绉扮粍
+     * @return 鏁版嵁搴撹〃闆嗗悎
+     */
+    @Override
+    public List<GenTable> selectDbTableListByNames(String[] tableNames)
+    {
+        return genTableMapper.selectDbTableListByNames(tableNames);
+    }
+
+    /**
+     * 鏌ヨ鎵�鏈夎〃淇℃伅
+     * 
+     * @return 琛ㄤ俊鎭泦鍚�
+     */
+    @Override
+    public List<GenTable> selectGenTableAll()
+    {
+        return genTableMapper.selectGenTableAll();
+    }
+
+    /**
+     * 淇敼涓氬姟
+     * 
+     * @param genTable 涓氬姟淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    @Transactional
+    public void updateGenTable(GenTable genTable)
+    {
+        String options = JSON.toJSONString(genTable.getParams());
+        genTable.setOptions(options);
+        int row = genTableMapper.updateGenTable(genTable);
+        if (row > 0)
+        {
+            for (GenTableColumn cenTableColumn : genTable.getColumns())
+            {
+                genTableColumnMapper.updateGenTableColumn(cenTableColumn);
+            }
+        }
+    }
+
+    /**
+     * 鍒犻櫎涓氬姟瀵硅薄
+     * 
+     * @param tableIds 闇�瑕佸垹闄ょ殑鏁版嵁ID
+     * @return 缁撴灉
+     */
+    @Override
+    @Transactional
+    public void deleteGenTableByIds(Long[] tableIds)
+    {
+        genTableMapper.deleteGenTableByIds(tableIds);
+        genTableColumnMapper.deleteGenTableColumnByIds(tableIds);
+    }
+
+    /**
+     * 瀵煎叆琛ㄧ粨鏋�
+     * 
+     * @param tableList 瀵煎叆琛ㄥ垪琛�
+     */
+    @Override
+    @Transactional
+    public void importGenTable(List<GenTable> tableList)
+    {
+        String operName = SecurityUtils.getUsername();
+        try
+        {
+            for (GenTable table : tableList)
+            {
+                String tableName = table.getTableName();
+                GenUtils.initTable(table, operName);
+                int row = genTableMapper.insertGenTable(table);
+                if (row > 0)
+                {
+                    // 淇濆瓨鍒椾俊鎭�
+                    List<GenTableColumn> genTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
+                    for (GenTableColumn column : genTableColumns)
+                    {
+                        GenUtils.initColumnField(column, table);
+                        genTableColumnMapper.insertGenTableColumn(column);
+                    }
+                }
+            }
+        }
+        catch (Exception e)
+        {
+            throw new ServiceException("瀵煎叆澶辫触锛�" + e.getMessage());
+        }
+    }
+
+    /**
+     * 棰勮浠g爜
+     * 
+     * @param tableId 琛ㄧ紪鍙�
+     * @return 棰勮鏁版嵁鍒楄〃
+     */
+    @Override
+    public Map<String, String> previewCode(Long tableId)
+    {
+        Map<String, String> dataMap = new LinkedHashMap<>();
+        // 鏌ヨ琛ㄤ俊鎭�
+        GenTable table = genTableMapper.selectGenTableById(tableId);
+        // 璁剧疆涓诲瓙琛ㄤ俊鎭�
+        setSubTable(table);
+        // 璁剧疆涓婚敭鍒椾俊鎭�
+        setPkColumn(table);
+        VelocityInitializer.initVelocity();
+
+        VelocityContext context = VelocityUtils.prepareContext(table);
+
+        // 鑾峰彇妯℃澘鍒楄〃
+        List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory(), table.getTplWebType());
+        for (String template : templates)
+        {
+            // 娓叉煋妯℃澘
+            StringWriter sw = new StringWriter();
+            Template tpl = Velocity.getTemplate(template, Constants.UTF8);
+            tpl.merge(context, sw);
+            dataMap.put(template, sw.toString());
+        }
+        return dataMap;
+    }
+
+    /**
+     * 鐢熸垚浠g爜锛堜笅杞芥柟寮忥級
+     * 
+     * @param tableName 琛ㄥ悕绉�
+     * @return 鏁版嵁
+     */
+    @Override
+    public byte[] downloadCode(String tableName)
+    {
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        ZipOutputStream zip = new ZipOutputStream(outputStream);
+        generatorCode(tableName, zip);
+        IOUtils.closeQuietly(zip);
+        return outputStream.toByteArray();
+    }
+
+    /**
+     * 鐢熸垚浠g爜锛堣嚜瀹氫箟璺緞锛�
+     * 
+     * @param tableName 琛ㄥ悕绉�
+     */
+    @Override
+    public void generatorCode(String tableName)
+    {
+        // 鏌ヨ琛ㄤ俊鎭�
+        GenTable table = genTableMapper.selectGenTableByName(tableName);
+        // 璁剧疆涓诲瓙琛ㄤ俊鎭�
+        setSubTable(table);
+        // 璁剧疆涓婚敭鍒椾俊鎭�
+        setPkColumn(table);
+
+        VelocityInitializer.initVelocity();
+
+        VelocityContext context = VelocityUtils.prepareContext(table);
+
+        // 鑾峰彇妯℃澘鍒楄〃
+        List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory(), table.getTplWebType());
+        for (String template : templates)
+        {
+            if (!StringUtils.containsAny(template, "sql.vm", "api.js.vm", "index.vue.vm", "index-tree.vue.vm"))
+            {
+                // 娓叉煋妯℃澘
+                StringWriter sw = new StringWriter();
+                Template tpl = Velocity.getTemplate(template, Constants.UTF8);
+                tpl.merge(context, sw);
+                try
+                {
+                    String path = getGenPath(table, template);
+                    FileUtils.writeStringToFile(new File(path), sw.toString(), CharsetKit.UTF_8);
+                }
+                catch (IOException e)
+                {
+                    throw new ServiceException("娓叉煋妯℃澘澶辫触锛岃〃鍚嶏細" + table.getTableName());
+                }
+            }
+        }
+    }
+
+    /**
+     * 鍚屾鏁版嵁搴�
+     * 
+     * @param tableName 琛ㄥ悕绉�
+     */
+    @Override
+    @Transactional
+    public void synchDb(String tableName)
+    {
+        GenTable table = genTableMapper.selectGenTableByName(tableName);
+        List<GenTableColumn> tableColumns = table.getColumns();
+        Map<String, GenTableColumn> tableColumnMap = tableColumns.stream().collect(Collectors.toMap(GenTableColumn::getColumnName, Function.identity()));
+
+        List<GenTableColumn> dbTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
+        if (StringUtils.isEmpty(dbTableColumns))
+        {
+            throw new ServiceException("鍚屾鏁版嵁澶辫触锛屽師琛ㄧ粨鏋勪笉瀛樺湪");
+        }
+        List<String> dbTableColumnNames = dbTableColumns.stream().map(GenTableColumn::getColumnName).collect(Collectors.toList());
+
+        dbTableColumns.forEach(column -> {
+            GenUtils.initColumnField(column, table);
+            if (tableColumnMap.containsKey(column.getColumnName()))
+            {
+                GenTableColumn prevColumn = tableColumnMap.get(column.getColumnName());
+                column.setColumnId(prevColumn.getColumnId());
+                if (column.isList())
+                {
+                    // 濡傛灉鏄垪琛紝缁х画淇濈暀鏌ヨ鏂瑰紡/瀛楀吀绫诲瀷閫夐」
+                    column.setDictType(prevColumn.getDictType());
+                    column.setQueryType(prevColumn.getQueryType());
+                }
+                if (StringUtils.isNotEmpty(prevColumn.getIsRequired()) && !column.isPk()
+                        && (column.isInsert() || column.isEdit())
+                        && ((column.isUsableColumn()) || (!column.isSuperColumn())))
+                {
+                    // 濡傛灉鏄�(鏂板/淇敼&闈炰富閿�/闈炲拷鐣ュ強鐖跺睘鎬�)锛岀户缁繚鐣欏繀濉�/鏄剧ず绫诲瀷閫夐」
+                    column.setIsRequired(prevColumn.getIsRequired());
+                    column.setHtmlType(prevColumn.getHtmlType());
+                }
+                genTableColumnMapper.updateGenTableColumn(column);
+            }
+            else
+            {
+                genTableColumnMapper.insertGenTableColumn(column);
+            }
+        });
+
+        List<GenTableColumn> delColumns = tableColumns.stream().filter(column -> !dbTableColumnNames.contains(column.getColumnName())).collect(Collectors.toList());
+        if (StringUtils.isNotEmpty(delColumns))
+        {
+            genTableColumnMapper.deleteGenTableColumns(delColumns);
+        }
+    }
+
+    /**
+     * 鎵归噺鐢熸垚浠g爜锛堜笅杞芥柟寮忥級
+     * 
+     * @param tableNames 琛ㄦ暟缁�
+     * @return 鏁版嵁
+     */
+    @Override
+    public byte[] downloadCode(String[] tableNames)
+    {
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        ZipOutputStream zip = new ZipOutputStream(outputStream);
+        for (String tableName : tableNames)
+        {
+            generatorCode(tableName, zip);
+        }
+        IOUtils.closeQuietly(zip);
+        return outputStream.toByteArray();
+    }
+
+    /**
+     * 鏌ヨ琛ㄤ俊鎭苟鐢熸垚浠g爜
+     */
+    private void generatorCode(String tableName, ZipOutputStream zip)
+    {
+        // 鏌ヨ琛ㄤ俊鎭�
+        GenTable table = genTableMapper.selectGenTableByName(tableName);
+        // 璁剧疆涓诲瓙琛ㄤ俊鎭�
+        setSubTable(table);
+        // 璁剧疆涓婚敭鍒椾俊鎭�
+        setPkColumn(table);
+
+        VelocityInitializer.initVelocity();
+
+        VelocityContext context = VelocityUtils.prepareContext(table);
+
+        // 鑾峰彇妯℃澘鍒楄〃
+        List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory(), table.getTplWebType());
+        for (String template : templates)
+        {
+            // 娓叉煋妯℃澘
+            StringWriter sw = new StringWriter();
+            Template tpl = Velocity.getTemplate(template, Constants.UTF8);
+            tpl.merge(context, sw);
+            try
+            {
+                // 娣诲姞鍒皕ip
+                zip.putNextEntry(new ZipEntry(VelocityUtils.getFileName(template, table)));
+                IOUtils.write(sw.toString(), zip, Constants.UTF8);
+                IOUtils.closeQuietly(sw);
+                zip.flush();
+                zip.closeEntry();
+            }
+            catch (IOException e)
+            {
+                log.error("娓叉煋妯℃澘澶辫触锛岃〃鍚嶏細" + table.getTableName(), e);
+            }
+        }
+    }
+
+    /**
+     * 淇敼淇濆瓨鍙傛暟鏍¢獙
+     * 
+     * @param genTable 涓氬姟淇℃伅
+     */
+    @Override
+    public void validateEdit(GenTable genTable)
+    {
+        if (GenConstants.TPL_TREE.equals(genTable.getTplCategory()))
+        {
+            String options = JSON.toJSONString(genTable.getParams());
+            JSONObject paramsObj = JSON.parseObject(options);
+            if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_CODE)))
+            {
+                throw new ServiceException("鏍戠紪鐮佸瓧娈典笉鑳戒负绌�");
+            }
+            else if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_PARENT_CODE)))
+            {
+                throw new ServiceException("鏍戠埗缂栫爜瀛楁涓嶈兘涓虹┖");
+            }
+            else if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_NAME)))
+            {
+                throw new ServiceException("鏍戝悕绉板瓧娈典笉鑳戒负绌�");
+            }
+            else if (GenConstants.TPL_SUB.equals(genTable.getTplCategory()))
+            {
+                if (StringUtils.isEmpty(genTable.getSubTableName()))
+                {
+                    throw new ServiceException("鍏宠仈瀛愯〃鐨勮〃鍚嶄笉鑳戒负绌�");
+                }
+                else if (StringUtils.isEmpty(genTable.getSubTableFkName()))
+                {
+                    throw new ServiceException("瀛愯〃鍏宠仈鐨勫閿悕涓嶈兘涓虹┖");
+                }
+            }
+        }
+    }
+
+    /**
+     * 璁剧疆涓婚敭鍒椾俊鎭�
+     * 
+     * @param table 涓氬姟琛ㄤ俊鎭�
+     */
+    public void setPkColumn(GenTable table)
+    {
+        for (GenTableColumn column : table.getColumns())
+        {
+            if (column.isPk())
+            {
+                table.setPkColumn(column);
+                break;
+            }
+        }
+        if (StringUtils.isNull(table.getPkColumn()))
+        {
+            table.setPkColumn(table.getColumns().get(0));
+        }
+        if (GenConstants.TPL_SUB.equals(table.getTplCategory()))
+        {
+            for (GenTableColumn column : table.getSubTable().getColumns())
+            {
+                if (column.isPk())
+                {
+                    table.getSubTable().setPkColumn(column);
+                    break;
+                }
+            }
+            if (StringUtils.isNull(table.getSubTable().getPkColumn()))
+            {
+                table.getSubTable().setPkColumn(table.getSubTable().getColumns().get(0));
+            }
+        }
+    }
+
+    /**
+     * 璁剧疆涓诲瓙琛ㄤ俊鎭�
+     * 
+     * @param table 涓氬姟琛ㄤ俊鎭�
+     */
+    public void setSubTable(GenTable table)
+    {
+        String subTableName = table.getSubTableName();
+        if (StringUtils.isNotEmpty(subTableName))
+        {
+            table.setSubTable(genTableMapper.selectGenTableByName(subTableName));
+        }
+    }
+
+    /**
+     * 璁剧疆浠g爜鐢熸垚鍏朵粬閫夐」鍊�
+     * 
+     * @param genTable 璁剧疆鍚庣殑鐢熸垚瀵硅薄
+     */
+    public void setTableFromOptions(GenTable genTable)
+    {
+        JSONObject paramsObj = JSON.parseObject(genTable.getOptions());
+        if (StringUtils.isNotNull(paramsObj))
+        {
+            String treeCode = paramsObj.getString(GenConstants.TREE_CODE);
+            String treeParentCode = paramsObj.getString(GenConstants.TREE_PARENT_CODE);
+            String treeName = paramsObj.getString(GenConstants.TREE_NAME);
+            String parentMenuId = paramsObj.getString(GenConstants.PARENT_MENU_ID);
+            String parentMenuName = paramsObj.getString(GenConstants.PARENT_MENU_NAME);
+
+            genTable.setTreeCode(treeCode);
+            genTable.setTreeParentCode(treeParentCode);
+            genTable.setTreeName(treeName);
+            genTable.setParentMenuId(parentMenuId);
+            genTable.setParentMenuName(parentMenuName);
+        }
+    }
+
+    /**
+     * 鑾峰彇浠g爜鐢熸垚鍦板潃
+     * 
+     * @param table 涓氬姟琛ㄤ俊鎭�
+     * @param template 妯℃澘鏂囦欢璺緞
+     * @return 鐢熸垚鍦板潃
+     */
+    public static String getGenPath(GenTable table, String template)
+    {
+        String genPath = table.getGenPath();
+        if (StringUtils.equals(genPath, "/"))
+        {
+            return System.getProperty("user.dir") + File.separator + "src" + File.separator + VelocityUtils.getFileName(template, table);
+        }
+        return genPath + File.separator + VelocityUtils.getFileName(template, table);
+    }
+}
\ No newline at end of file
diff --git a/jcdm-generator/src/main/java/com/jcdm/generator/service/IGenTableColumnService.java b/jcdm-generator/src/main/java/com/jcdm/generator/service/IGenTableColumnService.java
new file mode 100644
index 0000000..2e8afe4
--- /dev/null
+++ b/jcdm-generator/src/main/java/com/jcdm/generator/service/IGenTableColumnService.java
@@ -0,0 +1,44 @@
+package com.jcdm.generator.service;
+
+import java.util.List;
+import com.jcdm.generator.domain.GenTableColumn;
+
+/**
+ * 涓氬姟瀛楁 鏈嶅姟灞�
+ * 
+ * @author jc
+ */
+public interface IGenTableColumnService
+{
+    /**
+     * 鏌ヨ涓氬姟瀛楁鍒楄〃
+     * 
+     * @param tableId 涓氬姟瀛楁缂栧彿
+     * @return 涓氬姟瀛楁闆嗗悎
+     */
+    public List<GenTableColumn> selectGenTableColumnListByTableId(Long tableId);
+
+    /**
+     * 鏂板涓氬姟瀛楁
+     * 
+     * @param genTableColumn 涓氬姟瀛楁淇℃伅
+     * @return 缁撴灉
+     */
+    public int insertGenTableColumn(GenTableColumn genTableColumn);
+
+    /**
+     * 淇敼涓氬姟瀛楁
+     * 
+     * @param genTableColumn 涓氬姟瀛楁淇℃伅
+     * @return 缁撴灉
+     */
+    public int updateGenTableColumn(GenTableColumn genTableColumn);
+
+    /**
+     * 鍒犻櫎涓氬姟瀛楁淇℃伅
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁ID
+     * @return 缁撴灉
+     */
+    public int deleteGenTableColumnByIds(String ids);
+}
diff --git a/jcdm-generator/src/main/java/com/jcdm/generator/service/IGenTableService.java b/jcdm-generator/src/main/java/com/jcdm/generator/service/IGenTableService.java
new file mode 100644
index 0000000..11d06a2
--- /dev/null
+++ b/jcdm-generator/src/main/java/com/jcdm/generator/service/IGenTableService.java
@@ -0,0 +1,121 @@
+package com.jcdm.generator.service;
+
+import java.util.List;
+import java.util.Map;
+import com.jcdm.generator.domain.GenTable;
+
+/**
+ * 涓氬姟 鏈嶅姟灞�
+ * 
+ * @author jc
+ */
+public interface IGenTableService
+{
+    /**
+     * 鏌ヨ涓氬姟鍒楄〃
+     * 
+     * @param genTable 涓氬姟淇℃伅
+     * @return 涓氬姟闆嗗悎
+     */
+    public List<GenTable> selectGenTableList(GenTable genTable);
+
+    /**
+     * 鏌ヨ鎹簱鍒楄〃
+     * 
+     * @param genTable 涓氬姟淇℃伅
+     * @return 鏁版嵁搴撹〃闆嗗悎
+     */
+    public List<GenTable> selectDbTableList(GenTable genTable);
+
+    /**
+     * 鏌ヨ鎹簱鍒楄〃
+     * 
+     * @param tableNames 琛ㄥ悕绉扮粍
+     * @return 鏁版嵁搴撹〃闆嗗悎
+     */
+    public List<GenTable> selectDbTableListByNames(String[] tableNames);
+
+    /**
+     * 鏌ヨ鎵�鏈夎〃淇℃伅
+     * 
+     * @return 琛ㄤ俊鎭泦鍚�
+     */
+    public List<GenTable> selectGenTableAll();
+
+    /**
+     * 鏌ヨ涓氬姟淇℃伅
+     * 
+     * @param id 涓氬姟ID
+     * @return 涓氬姟淇℃伅
+     */
+    public GenTable selectGenTableById(Long id);
+
+    /**
+     * 淇敼涓氬姟
+     * 
+     * @param genTable 涓氬姟淇℃伅
+     * @return 缁撴灉
+     */
+    public void updateGenTable(GenTable genTable);
+
+    /**
+     * 鍒犻櫎涓氬姟淇℃伅
+     * 
+     * @param tableIds 闇�瑕佸垹闄ょ殑琛ㄦ暟鎹甀D
+     * @return 缁撴灉
+     */
+    public void deleteGenTableByIds(Long[] tableIds);
+
+    /**
+     * 瀵煎叆琛ㄧ粨鏋�
+     * 
+     * @param tableList 瀵煎叆琛ㄥ垪琛�
+     */
+    public void importGenTable(List<GenTable> tableList);
+
+    /**
+     * 棰勮浠g爜
+     * 
+     * @param tableId 琛ㄧ紪鍙�
+     * @return 棰勮鏁版嵁鍒楄〃
+     */
+    public Map<String, String> previewCode(Long tableId);
+
+    /**
+     * 鐢熸垚浠g爜锛堜笅杞芥柟寮忥級
+     * 
+     * @param tableName 琛ㄥ悕绉�
+     * @return 鏁版嵁
+     */
+    public byte[] downloadCode(String tableName);
+
+    /**
+     * 鐢熸垚浠g爜锛堣嚜瀹氫箟璺緞锛�
+     * 
+     * @param tableName 琛ㄥ悕绉�
+     * @return 鏁版嵁
+     */
+    public void generatorCode(String tableName);
+
+    /**
+     * 鍚屾鏁版嵁搴�
+     * 
+     * @param tableName 琛ㄥ悕绉�
+     */
+    public void synchDb(String tableName);
+
+    /**
+     * 鎵归噺鐢熸垚浠g爜锛堜笅杞芥柟寮忥級
+     * 
+     * @param tableNames 琛ㄦ暟缁�
+     * @return 鏁版嵁
+     */
+    public byte[] downloadCode(String[] tableNames);
+
+    /**
+     * 淇敼淇濆瓨鍙傛暟鏍¢獙
+     * 
+     * @param genTable 涓氬姟淇℃伅
+     */
+    public void validateEdit(GenTable genTable);
+}
diff --git a/jcdm-generator/src/main/java/com/jcdm/generator/util/GenUtils.java b/jcdm-generator/src/main/java/com/jcdm/generator/util/GenUtils.java
new file mode 100644
index 0000000..59aec04
--- /dev/null
+++ b/jcdm-generator/src/main/java/com/jcdm/generator/util/GenUtils.java
@@ -0,0 +1,257 @@
+package com.jcdm.generator.util;
+
+import java.util.Arrays;
+import org.apache.commons.lang3.RegExUtils;
+import com.jcdm.common.constant.GenConstants;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.generator.config.GenConfig;
+import com.jcdm.generator.domain.GenTable;
+import com.jcdm.generator.domain.GenTableColumn;
+
+/**
+ * 浠g爜鐢熸垚鍣� 宸ュ叿绫�
+ * 
+ * @author jc
+ */
+public class GenUtils
+{
+    /**
+     * 鍒濆鍖栬〃淇℃伅
+     */
+    public static void initTable(GenTable genTable, String operName)
+    {
+        genTable.setClassName(convertClassName(genTable.getTableName()));
+        genTable.setPackageName(GenConfig.getPackageName());
+        genTable.setModuleName(getModuleName(GenConfig.getPackageName()));
+        genTable.setBusinessName(getBusinessName(genTable.getTableName()));
+        genTable.setFunctionName(replaceText(genTable.getTableComment()));
+        genTable.setFunctionAuthor(GenConfig.getAuthor());
+        genTable.setCreateBy(operName);
+    }
+
+    /**
+     * 鍒濆鍖栧垪灞炴�у瓧娈�
+     */
+    public static void initColumnField(GenTableColumn column, GenTable table)
+    {
+        String dataType = getDbType(column.getColumnType());
+        String columnName = column.getColumnName();
+        column.setTableId(table.getTableId());
+        column.setCreateBy(table.getCreateBy());
+        // 璁剧疆java瀛楁鍚�
+        column.setJavaField(StringUtils.toCamelCase(columnName));
+        // 璁剧疆榛樿绫诲瀷
+        column.setJavaType(GenConstants.TYPE_STRING);
+        column.setQueryType(GenConstants.QUERY_EQ);
+
+        if (arraysContains(GenConstants.COLUMNTYPE_STR, dataType) || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType))
+        {
+            // 瀛楃涓查暱搴﹁秴杩�500璁剧疆涓烘枃鏈煙
+            Integer columnLength = getColumnLength(column.getColumnType());
+            String htmlType = columnLength >= 500 || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType) ? GenConstants.HTML_TEXTAREA : GenConstants.HTML_INPUT;
+            column.setHtmlType(htmlType);
+        }
+        else if (arraysContains(GenConstants.COLUMNTYPE_TIME, dataType))
+        {
+            column.setJavaType(GenConstants.TYPE_DATE);
+            column.setHtmlType(GenConstants.HTML_DATETIME);
+        }
+        else if (arraysContains(GenConstants.COLUMNTYPE_NUMBER, dataType))
+        {
+            column.setHtmlType(GenConstants.HTML_INPUT);
+
+            // 濡傛灉鏄诞鐐瑰瀷 缁熶竴鐢˙igDecimal
+            String[] str = StringUtils.split(StringUtils.substringBetween(column.getColumnType(), "(", ")"), ",");
+            if (str != null && str.length == 2 && Integer.parseInt(str[1]) > 0)
+            {
+                column.setJavaType(GenConstants.TYPE_BIGDECIMAL);
+            }
+            // 濡傛灉鏄暣褰�
+            else if (str != null && str.length == 1 && Integer.parseInt(str[0]) <= 10)
+            {
+                column.setJavaType(GenConstants.TYPE_INTEGER);
+            }
+            // 闀挎暣褰�
+            else
+            {
+                column.setJavaType(GenConstants.TYPE_LONG);
+            }
+        }
+
+        // 鎻掑叆瀛楁锛堥粯璁ゆ墍鏈夊瓧娈甸兘闇�瑕佹彃鍏ワ級
+        column.setIsInsert(GenConstants.REQUIRE);
+
+        // 缂栬緫瀛楁
+        if (!arraysContains(GenConstants.COLUMNNAME_NOT_EDIT, columnName) && !column.isPk())
+        {
+            column.setIsEdit(GenConstants.REQUIRE);
+        }
+        // 鍒楄〃瀛楁
+        if (!arraysContains(GenConstants.COLUMNNAME_NOT_LIST, columnName) && !column.isPk())
+        {
+            column.setIsList(GenConstants.REQUIRE);
+        }
+        // 鏌ヨ瀛楁
+        if (!arraysContains(GenConstants.COLUMNNAME_NOT_QUERY, columnName) && !column.isPk())
+        {
+            column.setIsQuery(GenConstants.REQUIRE);
+        }
+
+        // 鏌ヨ瀛楁绫诲瀷
+        if (StringUtils.endsWithIgnoreCase(columnName, "name"))
+        {
+            column.setQueryType(GenConstants.QUERY_LIKE);
+        }
+        // 鐘舵�佸瓧娈佃缃崟閫夋
+        if (StringUtils.endsWithIgnoreCase(columnName, "status"))
+        {
+            column.setHtmlType(GenConstants.HTML_RADIO);
+        }
+        // 绫诲瀷&鎬у埆瀛楁璁剧疆涓嬫媺妗�
+        else if (StringUtils.endsWithIgnoreCase(columnName, "type")
+                || StringUtils.endsWithIgnoreCase(columnName, "sex"))
+        {
+            column.setHtmlType(GenConstants.HTML_SELECT);
+        }
+        // 鍥剧墖瀛楁璁剧疆鍥剧墖涓婁紶鎺т欢
+        else if (StringUtils.endsWithIgnoreCase(columnName, "image"))
+        {
+            column.setHtmlType(GenConstants.HTML_IMAGE_UPLOAD);
+        }
+        // 鏂囦欢瀛楁璁剧疆鏂囦欢涓婁紶鎺т欢
+        else if (StringUtils.endsWithIgnoreCase(columnName, "file"))
+        {
+            column.setHtmlType(GenConstants.HTML_FILE_UPLOAD);
+        }
+        // 鍐呭瀛楁璁剧疆瀵屾枃鏈帶浠�
+        else if (StringUtils.endsWithIgnoreCase(columnName, "content"))
+        {
+            column.setHtmlType(GenConstants.HTML_EDITOR);
+        }
+    }
+
+    /**
+     * 鏍¢獙鏁扮粍鏄惁鍖呭惈鎸囧畾鍊�
+     * 
+     * @param arr 鏁扮粍
+     * @param targetValue 鍊�
+     * @return 鏄惁鍖呭惈
+     */
+    public static boolean arraysContains(String[] arr, String targetValue)
+    {
+        return Arrays.asList(arr).contains(targetValue);
+    }
+
+    /**
+     * 鑾峰彇妯″潡鍚�
+     * 
+     * @param packageName 鍖呭悕
+     * @return 妯″潡鍚�
+     */
+    public static String getModuleName(String packageName)
+    {
+        int lastIndex = packageName.lastIndexOf(".");
+        int nameLength = packageName.length();
+        return StringUtils.substring(packageName, lastIndex + 1, nameLength);
+    }
+
+    /**
+     * 鑾峰彇涓氬姟鍚�
+     * 
+     * @param tableName 琛ㄥ悕
+     * @return 涓氬姟鍚�
+     */
+    public static String getBusinessName(String tableName)
+    {
+        int lastIndex = tableName.lastIndexOf("_");
+        int nameLength = tableName.length();
+        return StringUtils.substring(tableName, lastIndex + 1, nameLength);
+    }
+
+    /**
+     * 琛ㄥ悕杞崲鎴怞ava绫诲悕
+     * 
+     * @param tableName 琛ㄥ悕绉�
+     * @return 绫诲悕
+     */
+    public static String convertClassName(String tableName)
+    {
+        boolean autoRemovePre = GenConfig.getAutoRemovePre();
+        String tablePrefix = GenConfig.getTablePrefix();
+        if (autoRemovePre && StringUtils.isNotEmpty(tablePrefix))
+        {
+            String[] searchList = StringUtils.split(tablePrefix, ",");
+            tableName = replaceFirst(tableName, searchList);
+        }
+        return StringUtils.convertToCamelCase(tableName);
+    }
+
+    /**
+     * 鎵归噺鏇挎崲鍓嶇紑
+     * 
+     * @param replacementm 鏇挎崲鍊�
+     * @param searchList 鏇挎崲鍒楄〃
+     * @return
+     */
+    public static String replaceFirst(String replacementm, String[] searchList)
+    {
+        String text = replacementm;
+        for (String searchString : searchList)
+        {
+            if (replacementm.startsWith(searchString))
+            {
+                text = replacementm.replaceFirst(searchString, "");
+                break;
+            }
+        }
+        return text;
+    }
+
+    /**
+     * 鍏抽敭瀛楁浛鎹�
+     * 
+     * @param text 闇�瑕佽鏇挎崲鐨勫悕瀛�
+     * @return 鏇挎崲鍚庣殑鍚嶅瓧
+     */
+    public static String replaceText(String text)
+    {
+        return RegExUtils.replaceAll(text, "(?:琛▅鑻ヤ緷)", "");
+    }
+
+    /**
+     * 鑾峰彇鏁版嵁搴撶被鍨嬪瓧娈�
+     * 
+     * @param columnType 鍒楃被鍨�
+     * @return 鎴彇鍚庣殑鍒楃被鍨�
+     */
+    public static String getDbType(String columnType)
+    {
+        if (StringUtils.indexOf(columnType, "(") > 0)
+        {
+            return StringUtils.substringBefore(columnType, "(");
+        }
+        else
+        {
+            return columnType;
+        }
+    }
+
+    /**
+     * 鑾峰彇瀛楁闀垮害
+     * 
+     * @param columnType 鍒楃被鍨�
+     * @return 鎴彇鍚庣殑鍒楃被鍨�
+     */
+    public static Integer getColumnLength(String columnType)
+    {
+        if (StringUtils.indexOf(columnType, "(") > 0)
+        {
+            String length = StringUtils.substringBetween(columnType, "(", ")");
+            return Integer.valueOf(length);
+        }
+        else
+        {
+            return 0;
+        }
+    }
+}
diff --git a/jcdm-generator/src/main/java/com/jcdm/generator/util/VelocityInitializer.java b/jcdm-generator/src/main/java/com/jcdm/generator/util/VelocityInitializer.java
new file mode 100644
index 0000000..90b9648
--- /dev/null
+++ b/jcdm-generator/src/main/java/com/jcdm/generator/util/VelocityInitializer.java
@@ -0,0 +1,34 @@
+package com.jcdm.generator.util;
+
+import java.util.Properties;
+import org.apache.velocity.app.Velocity;
+import com.jcdm.common.constant.Constants;
+
+/**
+ * VelocityEngine宸ュ巶
+ * 
+ * @author jc
+ */
+public class VelocityInitializer
+{
+    /**
+     * 鍒濆鍖杤m鏂规硶
+     */
+    public static void initVelocity()
+    {
+        Properties p = new Properties();
+        try
+        {
+            // 鍔犺浇classpath鐩綍涓嬬殑vm鏂囦欢
+            p.setProperty("resource.loader.file.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
+            // 瀹氫箟瀛楃闆�
+            p.setProperty(Velocity.INPUT_ENCODING, Constants.UTF8);
+            // 鍒濆鍖朧elocity寮曟搸锛屾寚瀹氶厤缃甈roperties
+            Velocity.init(p);
+        }
+        catch (Exception e)
+        {
+            throw new RuntimeException(e);
+        }
+    }
+}
diff --git a/jcdm-generator/src/main/java/com/jcdm/generator/util/VelocityUtils.java b/jcdm-generator/src/main/java/com/jcdm/generator/util/VelocityUtils.java
new file mode 100644
index 0000000..efc633e
--- /dev/null
+++ b/jcdm-generator/src/main/java/com/jcdm/generator/util/VelocityUtils.java
@@ -0,0 +1,408 @@
+package com.jcdm.generator.util;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.velocity.VelocityContext;
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import com.jcdm.common.constant.GenConstants;
+import com.jcdm.common.utils.DateUtils;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.generator.domain.GenTable;
+import com.jcdm.generator.domain.GenTableColumn;
+
+/**
+ * 妯℃澘澶勭悊宸ュ叿绫�
+ * 
+ * @author jc
+ */
+public class VelocityUtils
+{
+    /** 椤圭洰绌洪棿璺緞 */
+    private static final String PROJECT_PATH = "main/java";
+
+    /** mybatis绌洪棿璺緞 */
+    private static final String MYBATIS_PATH = "main/resources/mapper";
+
+    /** 榛樿涓婄骇鑿滃崟锛岀郴缁熷伐鍏� */
+    private static final String DEFAULT_PARENT_MENU_ID = "3";
+
+    /**
+     * 璁剧疆妯℃澘鍙橀噺淇℃伅
+     *
+     * @return 妯℃澘鍒楄〃
+     */
+    public static VelocityContext prepareContext(GenTable genTable)
+    {
+        String moduleName = genTable.getModuleName();
+        String businessName = genTable.getBusinessName();
+        String packageName = genTable.getPackageName();
+        String tplCategory = genTable.getTplCategory();
+        String functionName = genTable.getFunctionName();
+
+        VelocityContext velocityContext = new VelocityContext();
+        velocityContext.put("tplCategory", genTable.getTplCategory());
+        velocityContext.put("tableName", genTable.getTableName());
+        velocityContext.put("functionName", StringUtils.isNotEmpty(functionName) ? functionName : "銆愯濉啓鍔熻兘鍚嶇О銆�");
+        velocityContext.put("ClassName", genTable.getClassName());
+        velocityContext.put("className", StringUtils.uncapitalize(genTable.getClassName()));
+        velocityContext.put("moduleName", genTable.getModuleName());
+        velocityContext.put("BusinessName", StringUtils.capitalize(genTable.getBusinessName()));
+        velocityContext.put("businessName", genTable.getBusinessName());
+        velocityContext.put("basePackage", getPackagePrefix(packageName));
+        velocityContext.put("packageName", packageName);
+        velocityContext.put("author", genTable.getFunctionAuthor());
+        velocityContext.put("datetime", DateUtils.getDate());
+        velocityContext.put("pkColumn", genTable.getPkColumn());
+        velocityContext.put("importList", getImportList(genTable));
+        velocityContext.put("permissionPrefix", getPermissionPrefix(moduleName, businessName));
+        velocityContext.put("columns", genTable.getColumns());
+        velocityContext.put("table", genTable);
+        velocityContext.put("dicts", getDicts(genTable));
+        setMenuVelocityContext(velocityContext, genTable);
+        if (GenConstants.TPL_TREE.equals(tplCategory))
+        {
+            setTreeVelocityContext(velocityContext, genTable);
+        }
+        if (GenConstants.TPL_SUB.equals(tplCategory))
+        {
+            setSubVelocityContext(velocityContext, genTable);
+        }
+        return velocityContext;
+    }
+
+    public static void setMenuVelocityContext(VelocityContext context, GenTable genTable)
+    {
+        String options = genTable.getOptions();
+        JSONObject paramsObj = JSON.parseObject(options);
+        String parentMenuId = getParentMenuId(paramsObj);
+        context.put("parentMenuId", parentMenuId);
+    }
+
+    public static void setTreeVelocityContext(VelocityContext context, GenTable genTable)
+    {
+        String options = genTable.getOptions();
+        JSONObject paramsObj = JSON.parseObject(options);
+        String treeCode = getTreecode(paramsObj);
+        String treeParentCode = getTreeParentCode(paramsObj);
+        String treeName = getTreeName(paramsObj);
+
+        context.put("treeCode", treeCode);
+        context.put("treeParentCode", treeParentCode);
+        context.put("treeName", treeName);
+        context.put("expandColumn", getExpandColumn(genTable));
+        if (paramsObj.containsKey(GenConstants.TREE_PARENT_CODE))
+        {
+            context.put("tree_parent_code", paramsObj.getString(GenConstants.TREE_PARENT_CODE));
+        }
+        if (paramsObj.containsKey(GenConstants.TREE_NAME))
+        {
+            context.put("tree_name", paramsObj.getString(GenConstants.TREE_NAME));
+        }
+    }
+
+    public static void setSubVelocityContext(VelocityContext context, GenTable genTable)
+    {
+        GenTable subTable = genTable.getSubTable();
+        String subTableName = genTable.getSubTableName();
+        String subTableFkName = genTable.getSubTableFkName();
+        String subClassName = genTable.getSubTable().getClassName();
+        String subTableFkClassName = StringUtils.convertToCamelCase(subTableFkName);
+
+        context.put("subTable", subTable);
+        context.put("subTableName", subTableName);
+        context.put("subTableFkName", subTableFkName);
+        context.put("subTableFkClassName", subTableFkClassName);
+        context.put("subTableFkclassName", StringUtils.uncapitalize(subTableFkClassName));
+        context.put("subClassName", subClassName);
+        context.put("subclassName", StringUtils.uncapitalize(subClassName));
+        context.put("subImportList", getImportList(genTable.getSubTable()));
+    }
+
+    /**
+     * 鑾峰彇妯℃澘淇℃伅
+     * @param tplCategory 鐢熸垚鐨勬ā鏉�
+     * @param tplWebType 鍓嶇绫诲瀷
+     * @return 妯℃澘鍒楄〃
+     */
+    public static List<String> getTemplateList(String tplCategory, String tplWebType)
+    {
+        String useWebType = "vm/vue";
+        if ("element-plus".equals(tplWebType))
+        {
+            useWebType = "vm/vue/v3";
+        }
+        List<String> templates = new ArrayList<String>();
+        templates.add("vm/java/domain.java.vm");
+        templates.add("vm/java/mapper.java.vm");
+        templates.add("vm/java/service.java.vm");
+        templates.add("vm/java/serviceImpl.java.vm");
+        templates.add("vm/java/controller.java.vm");
+        templates.add("vm/xml/mapper.xml.vm");
+        templates.add("vm/sql/sql.vm");
+        templates.add("vm/js/api.js.vm");
+        if (GenConstants.TPL_CRUD.equals(tplCategory))
+        {
+            templates.add(useWebType + "/index.vue.vm");
+        }
+        else if (GenConstants.TPL_TREE.equals(tplCategory))
+        {
+            templates.add(useWebType + "/index-tree.vue.vm");
+        }
+        else if (GenConstants.TPL_SUB.equals(tplCategory))
+        {
+            templates.add(useWebType + "/index.vue.vm");
+            templates.add("vm/java/sub-domain.java.vm");
+        }
+        return templates;
+    }
+
+    /**
+     * 鑾峰彇鏂囦欢鍚�
+     */
+    public static String getFileName(String template, GenTable genTable)
+    {
+        // 鏂囦欢鍚嶇О
+        String fileName = "";
+        // 鍖呰矾寰�
+        String packageName = genTable.getPackageName();
+        // 妯″潡鍚�
+        String moduleName = genTable.getModuleName();
+        // 澶у啓绫诲悕
+        String className = genTable.getClassName();
+        // 涓氬姟鍚嶇О
+        String businessName = genTable.getBusinessName();
+
+        String javaPath = PROJECT_PATH + "/" + StringUtils.replace(packageName, ".", "/");
+        String mybatisPath = MYBATIS_PATH + "/" + moduleName;
+        String vuePath = "vue";
+
+        if (template.contains("domain.java.vm"))
+        {
+            fileName = StringUtils.format("{}/domain/{}.java", javaPath, className);
+        }
+        if (template.contains("sub-domain.java.vm") && StringUtils.equals(GenConstants.TPL_SUB, genTable.getTplCategory()))
+        {
+            fileName = StringUtils.format("{}/domain/{}.java", javaPath, genTable.getSubTable().getClassName());
+        }
+        else if (template.contains("mapper.java.vm"))
+        {
+            fileName = StringUtils.format("{}/mapper/{}Mapper.java", javaPath, className);
+        }
+        else if (template.contains("service.java.vm"))
+        {
+            fileName = StringUtils.format("{}/service/I{}Service.java", javaPath, className);
+        }
+        else if (template.contains("serviceImpl.java.vm"))
+        {
+            fileName = StringUtils.format("{}/service/impl/{}ServiceImpl.java", javaPath, className);
+        }
+        else if (template.contains("controller.java.vm"))
+        {
+            fileName = StringUtils.format("{}/controller/{}Controller.java", javaPath, className);
+        }
+        else if (template.contains("mapper.xml.vm"))
+        {
+            fileName = StringUtils.format("{}/{}Mapper.xml", mybatisPath, className);
+        }
+        else if (template.contains("sql.vm"))
+        {
+            fileName = businessName + "Menu.sql";
+        }
+        else if (template.contains("api.js.vm"))
+        {
+            fileName = StringUtils.format("{}/api/{}/{}.js", vuePath, moduleName, businessName);
+        }
+        else if (template.contains("index.vue.vm"))
+        {
+            fileName = StringUtils.format("{}/views/{}/{}/index.vue", vuePath, moduleName, businessName);
+        }
+        else if (template.contains("index-tree.vue.vm"))
+        {
+            fileName = StringUtils.format("{}/views/{}/{}/index.vue", vuePath, moduleName, businessName);
+        }
+        return fileName;
+    }
+
+    /**
+     * 鑾峰彇鍖呭墠缂�
+     *
+     * @param packageName 鍖呭悕绉�
+     * @return 鍖呭墠缂�鍚嶇О
+     */
+    public static String getPackagePrefix(String packageName)
+    {
+        int lastIndex = packageName.lastIndexOf(".");
+        return StringUtils.substring(packageName, 0, lastIndex);
+    }
+
+    /**
+     * 鏍规嵁鍒楃被鍨嬭幏鍙栧鍏ュ寘
+     * 
+     * @param genTable 涓氬姟琛ㄥ璞�
+     * @return 杩斿洖闇�瑕佸鍏ョ殑鍖呭垪琛�
+     */
+    public static HashSet<String> getImportList(GenTable genTable)
+    {
+        List<GenTableColumn> columns = genTable.getColumns();
+        GenTable subGenTable = genTable.getSubTable();
+        HashSet<String> importList = new HashSet<String>();
+        if (StringUtils.isNotNull(subGenTable))
+        {
+            importList.add("java.util.List");
+        }
+        for (GenTableColumn column : columns)
+        {
+            if (!column.isSuperColumn() && GenConstants.TYPE_DATE.equals(column.getJavaType()))
+            {
+                importList.add("java.util.Date");
+                importList.add("com.fasterxml.jackson.annotation.JsonFormat");
+            }
+            else if (!column.isSuperColumn() && GenConstants.TYPE_BIGDECIMAL.equals(column.getJavaType()))
+            {
+                importList.add("java.math.BigDecimal");
+            }
+        }
+        return importList;
+    }
+
+    /**
+     * 鏍规嵁鍒楃被鍨嬭幏鍙栧瓧鍏哥粍
+     * 
+     * @param genTable 涓氬姟琛ㄥ璞�
+     * @return 杩斿洖瀛楀吀缁�
+     */
+    public static String getDicts(GenTable genTable)
+    {
+        List<GenTableColumn> columns = genTable.getColumns();
+        Set<String> dicts = new HashSet<String>();
+        addDicts(dicts, columns);
+        if (StringUtils.isNotNull(genTable.getSubTable()))
+        {
+            List<GenTableColumn> subColumns = genTable.getSubTable().getColumns();
+            addDicts(dicts, subColumns);
+        }
+        return StringUtils.join(dicts, ", ");
+    }
+
+    /**
+     * 娣诲姞瀛楀吀鍒楄〃
+     * 
+     * @param dicts 瀛楀吀鍒楄〃
+     * @param columns 鍒楅泦鍚�
+     */
+    public static void addDicts(Set<String> dicts, List<GenTableColumn> columns)
+    {
+        for (GenTableColumn column : columns)
+        {
+            if (!column.isSuperColumn() && StringUtils.isNotEmpty(column.getDictType()) && StringUtils.equalsAny(
+                    column.getHtmlType(),
+                    new String[] { GenConstants.HTML_SELECT, GenConstants.HTML_RADIO, GenConstants.HTML_CHECKBOX }))
+            {
+                dicts.add("'" + column.getDictType() + "'");
+            }
+        }
+    }
+
+    /**
+     * 鑾峰彇鏉冮檺鍓嶇紑
+     *
+     * @param moduleName 妯″潡鍚嶇О
+     * @param businessName 涓氬姟鍚嶇О
+     * @return 杩斿洖鏉冮檺鍓嶇紑
+     */
+    public static String getPermissionPrefix(String moduleName, String businessName)
+    {
+        return StringUtils.format("{}:{}", moduleName, businessName);
+    }
+
+    /**
+     * 鑾峰彇涓婄骇鑿滃崟ID瀛楁
+     *
+     * @param paramsObj 鐢熸垚鍏朵粬閫夐」
+     * @return 涓婄骇鑿滃崟ID瀛楁
+     */
+    public static String getParentMenuId(JSONObject paramsObj)
+    {
+        if (StringUtils.isNotEmpty(paramsObj) && paramsObj.containsKey(GenConstants.PARENT_MENU_ID)
+                && StringUtils.isNotEmpty(paramsObj.getString(GenConstants.PARENT_MENU_ID)))
+        {
+            return paramsObj.getString(GenConstants.PARENT_MENU_ID);
+        }
+        return DEFAULT_PARENT_MENU_ID;
+    }
+
+    /**
+     * 鑾峰彇鏍戠紪鐮�
+     *
+     * @param paramsObj 鐢熸垚鍏朵粬閫夐」
+     * @return 鏍戠紪鐮�
+     */
+    public static String getTreecode(JSONObject paramsObj)
+    {
+        if (paramsObj.containsKey(GenConstants.TREE_CODE))
+        {
+            return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_CODE));
+        }
+        return StringUtils.EMPTY;
+    }
+
+    /**
+     * 鑾峰彇鏍戠埗缂栫爜
+     *
+     * @param paramsObj 鐢熸垚鍏朵粬閫夐」
+     * @return 鏍戠埗缂栫爜
+     */
+    public static String getTreeParentCode(JSONObject paramsObj)
+    {
+        if (paramsObj.containsKey(GenConstants.TREE_PARENT_CODE))
+        {
+            return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_PARENT_CODE));
+        }
+        return StringUtils.EMPTY;
+    }
+
+    /**
+     * 鑾峰彇鏍戝悕绉�
+     *
+     * @param paramsObj 鐢熸垚鍏朵粬閫夐」
+     * @return 鏍戝悕绉�
+     */
+    public static String getTreeName(JSONObject paramsObj)
+    {
+        if (paramsObj.containsKey(GenConstants.TREE_NAME))
+        {
+            return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_NAME));
+        }
+        return StringUtils.EMPTY;
+    }
+
+    /**
+     * 鑾峰彇闇�瑕佸湪鍝竴鍒椾笂闈㈡樉绀哄睍寮�鎸夐挳
+     *
+     * @param genTable 涓氬姟琛ㄥ璞�
+     * @return 灞曞紑鎸夐挳鍒楀簭鍙�
+     */
+    public static int getExpandColumn(GenTable genTable)
+    {
+        String options = genTable.getOptions();
+        JSONObject paramsObj = JSON.parseObject(options);
+        String treeName = paramsObj.getString(GenConstants.TREE_NAME);
+        int num = 0;
+        for (GenTableColumn column : genTable.getColumns())
+        {
+            if (column.isList())
+            {
+                num++;
+                String columnName = column.getColumnName();
+                if (columnName.equals(treeName))
+                {
+                    break;
+                }
+            }
+        }
+        return num;
+    }
+}
diff --git a/jcdm-generator/src/main/resources/generator.yml b/jcdm-generator/src/main/resources/generator.yml
new file mode 100644
index 0000000..e47c154
--- /dev/null
+++ b/jcdm-generator/src/main/resources/generator.yml
@@ -0,0 +1,10 @@
+# 浠g爜鐢熸垚
+gen:
+  # 浣滆��
+  author: ruoyi
+  # 榛樿鐢熸垚鍖呰矾寰� system 闇�鏀规垚鑷繁鐨勬ā鍧楀悕绉� 濡� system monitor tool
+  packageName: com.jcdm.main
+  # 鑷姩鍘婚櫎琛ㄥ墠缂�锛岄粯璁ゆ槸false
+  autoRemovePre: false
+  # 琛ㄥ墠缂�锛堢敓鎴愮被鍚嶄笉浼氬寘鍚〃鍓嶇紑锛屽涓敤閫楀彿鍒嗛殧锛�
+  tablePrefix: sys_,bs_
\ No newline at end of file
diff --git a/jcdm-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml b/jcdm-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml
new file mode 100644
index 0000000..932c834
--- /dev/null
+++ b/jcdm-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.generator.mapper.GenTableColumnMapper">
+
+    <resultMap type="GenTableColumn" id="GenTableColumnResult">
+        <id     property="columnId"       column="column_id"      />
+        <result property="tableId"        column="table_id"       />
+        <result property="columnName"     column="column_name"    />
+        <result property="columnComment"  column="column_comment" />
+        <result property="columnType"     column="column_type"    />
+        <result property="javaType"       column="java_type"      />
+        <result property="javaField"      column="java_field"     />
+        <result property="isPk"           column="is_pk"          />
+        <result property="isIncrement"    column="is_increment"   />
+        <result property="isRequired"     column="is_required"    />
+        <result property="isInsert"       column="is_insert"      />
+        <result property="isEdit"         column="is_edit"        />
+        <result property="isList"         column="is_list"        />
+        <result property="isQuery"        column="is_query"       />
+        <result property="queryType"      column="query_type"     />
+        <result property="htmlType"       column="html_type"      />
+        <result property="dictType"       column="dict_type"      />
+        <result property="sort"           column="sort"           />
+        <result property="createBy"       column="create_by"      />
+        <result property="createTime"     column="create_time"    />
+        <result property="updateBy"       column="update_by"      />
+        <result property="updateTime"     column="update_time"    />
+    </resultMap>
+
+    <sql id="selectGenTableColumnVo">
+        select column_id, table_id, column_name, column_comment, column_type, java_type, java_field, is_pk, is_increment, is_required, is_insert, is_edit, is_list, is_query, query_type, html_type, dict_type, sort, create_by, create_time, update_by, update_time from gen_table_column
+    </sql>
+
+    <select id="selectGenTableColumnListByTableId" parameterType="Long" resultMap="GenTableColumnResult">
+        <include refid="selectGenTableColumnVo"/>
+        where table_id = #{tableId}
+        order by sort
+    </select>
+
+    <select id="selectDbTableColumnsByName" parameterType="String" resultMap="GenTableColumnResult">
+        SELECT a.name                                                                       AS column_name,
+               (CASE WHEN a.isnullable = 1 THEN 0 ELSE 1 END)                               AS is_required,
+               (CASE WHEN (
+                              SELECT COUNT(*) FROM sysobjects
+                              WHERE (name IN (
+                                  SELECT name FROM sysindexes
+                                  WHERE (id = a.id)
+                                    AND (indid IN (
+                                      SELECT indid FROM sysindexkeys
+                                      WHERE (id = a.id)
+                                        AND (colid IN (SELECT colid FROM syscolumns WHERE (id = a.id) AND (name = a.name)))
+                                  ))))
+                                AND (xtype = 'PK')
+                          ) > 0 THEN 1
+                     ELSE 0 END)                                                             AS is_pk,
+               a.colorder                                                                   AS sort,
+               isnull(g.[value], ' ')                                                       AS column_comment,
+               (CASE WHEN COLUMNPROPERTY(a.id, a.name, 'IsIdentity') = 1 THEN 1 ELSE 0 END) AS is_increment,
+               b.name                                                                       AS column_type
+        FROM syscolumns as a
+                 LEFT JOIN systypes b ON a.xtype = b.xusertype
+                 INNER JOIN sysobjects d ON a.id = d.id AND d.xtype = 'U' AND d.name <![CDATA[<>]]> 'dtproperties'
+                 LEFT JOIN syscomments e ON a.cdefault = e.id
+                 LEFT JOIN sys.extended_properties g ON a.id = g.major_id AND a.colid = g.minor_id
+                 LEFT JOIN sys.extended_properties f ON d.id = f.class AND f.minor_id = 0
+                 LEFT JOIN sys.objects h ON a.id = h.object_id
+                 LEFT JOIN sys.schemas i ON h.schema_id = i.schema_id
+        WHERE d.name = #{tableName}
+        ORDER BY a.colorder
+    </select>
+
+    <insert id="insertGenTableColumn" parameterType="GenTableColumn" useGeneratedKeys="true" keyProperty="columnId">
+        insert into gen_table_column (
+        <if test="tableId != null and tableId != ''">table_id,</if>
+        <if test="columnName != null and columnName != ''">column_name,</if>
+        <if test="columnComment != null and columnComment != ''">column_comment,</if>
+        <if test="columnType != null and columnType != ''">column_type,</if>
+        <if test="javaType != null and javaType != ''">java_type,</if>
+        <if test="javaField != null  and javaField != ''">java_field,</if>
+        <if test="isPk != null and isPk != ''">is_pk,</if>
+        <if test="isIncrement != null and isIncrement != ''">is_increment,</if>
+        <if test="isRequired != null and isRequired != ''">is_required,</if>
+        <if test="isInsert != null and isInsert != ''">is_insert,</if>
+        <if test="isEdit != null and isEdit != ''">is_edit,</if>
+        <if test="isList != null and isList != ''">is_list,</if>
+        <if test="isQuery != null and isQuery != ''">is_query,</if>
+        <if test="queryType != null and queryType != ''">query_type,</if>
+        <if test="htmlType != null and htmlType != ''">html_type,</if>
+        <if test="dictType != null and dictType != ''">dict_type,</if>
+        <if test="sort != null">sort,</if>
+        <if test="createBy != null and createBy != ''">create_by,</if>
+        create_time
+        )values(
+        <if test="tableId != null and tableId != ''">#{tableId},</if>
+        <if test="columnName != null and columnName != ''">#{columnName},</if>
+        <if test="columnComment != null and columnComment != ''">#{columnComment},</if>
+        <if test="columnType != null and columnType != ''">#{columnType},</if>
+        <if test="javaType != null and javaType != ''">#{javaType},</if>
+        <if test="javaField != null and javaField != ''">#{javaField},</if>
+        <if test="isPk != null and isPk != ''">#{isPk},</if>
+        <if test="isIncrement != null and isIncrement != ''">#{isIncrement},</if>
+        <if test="isRequired != null and isRequired != ''">#{isRequired},</if>
+        <if test="isInsert != null and isInsert != ''">#{isInsert},</if>
+        <if test="isEdit != null and isEdit != ''">#{isEdit},</if>
+        <if test="isList != null and isList != ''">#{isList},</if>
+        <if test="isQuery != null and isQuery != ''">#{isQuery},</if>
+        <if test="queryType != null and queryType != ''">#{queryType},</if>
+        <if test="htmlType != null and htmlType != ''">#{htmlType},</if>
+        <if test="dictType != null and dictType != ''">#{dictType},</if>
+        <if test="sort != null">#{sort},</if>
+        <if test="createBy != null and createBy != ''">#{createBy},</if>
+        getdate()
+        )
+    </insert>
+
+    <update id="updateGenTableColumn" parameterType="GenTableColumn">
+        update gen_table_column
+        <set>
+            is_insert = #{isInsert},
+            is_edit = #{isEdit},
+            is_list = #{isList},
+            is_query = #{isQuery},
+            is_required = #{isRequired},
+            <if test="columnComment != null">column_comment = #{columnComment},</if>
+            <if test="javaType != null">java_type = #{javaType},</if>
+            <if test="javaField != null">java_field = #{javaField},</if>
+            <if test="queryType != null">query_type = #{queryType},</if>
+            <if test="htmlType != null">html_type = #{htmlType},</if>
+            <if test="dictType != null">dict_type = #{dictType},</if>
+            <if test="sort != null">sort = #{sort},</if>
+            <if test="updateBy != null">update_by = #{updateBy},</if>
+            update_time = getdate()
+        </set>
+        where column_id = #{columnId}
+    </update>
+
+    <delete id="deleteGenTableColumnByIds" parameterType="Long">
+        delete from gen_table_column where table_id in
+        <foreach collection="array" item="tableId" open="(" separator="," close=")">
+            #{tableId}
+        </foreach>
+    </delete>
+
+    <delete id="deleteGenTableColumns">
+        delete from gen_table_column where column_id in
+        <foreach collection="list" item="item" open="(" separator="," close=")">
+            #{item.columnId}
+        </foreach>
+    </delete>
+
+</mapper>
\ No newline at end of file
diff --git a/jcdm-generator/src/main/resources/mapper/generator/GenTableMapper.xml b/jcdm-generator/src/main/resources/mapper/generator/GenTableMapper.xml
new file mode 100644
index 0000000..3edf1ec
--- /dev/null
+++ b/jcdm-generator/src/main/resources/mapper/generator/GenTableMapper.xml
@@ -0,0 +1,227 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+		PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+		"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.generator.mapper.GenTableMapper">
+
+	<resultMap type="GenTable" id="GenTableResult">
+		<id     property="tableId"        column="table_id"          />
+		<result property="tableName"      column="table_name"        />
+		<result property="tableComment"   column="table_comment"     />
+		<result property="subTableName"   column="sub_table_name"    />
+		<result property="subTableFkName" column="sub_table_fk_name" />
+		<result property="className"      column="class_name"        />
+		<result property="tplCategory"    column="tpl_category"      />
+		<result property="packageName"    column="package_name"      />
+		<result property="moduleName"     column="module_name"       />
+		<result property="businessName"   column="business_name"     />
+		<result property="functionName"   column="function_name"     />
+		<result property="functionAuthor" column="function_author"   />
+		<result property="genType"        column="gen_type"          />
+		<result property="genPath"        column="gen_path"          />
+		<result property="options"        column="options"           />
+		<result property="createBy"       column="create_by"         />
+		<result property="createTime"     column="create_time"       />
+		<result property="updateBy"       column="update_by"         />
+		<result property="updateTime"     column="update_time"       />
+		<result property="remark"         column="remark"            />
+		<collection  property="columns"  javaType="java.util.List"  resultMap="GenTableColumnResult" />
+	</resultMap>
+
+	<resultMap type="GenTableColumn" id="GenTableColumnResult">
+		<id     property="columnId"       column="column_id"      />
+		<result property="tableId"        column="table_id"       />
+		<result property="columnName"     column="column_name"    />
+		<result property="columnComment"  column="column_comment" />
+		<result property="columnType"     column="column_type"    />
+		<result property="javaType"       column="java_type"      />
+		<result property="javaField"      column="java_field"     />
+		<result property="isPk"           column="is_pk"          />
+		<result property="isIncrement"    column="is_increment"   />
+		<result property="isRequired"     column="is_required"    />
+		<result property="isInsert"       column="is_insert"      />
+		<result property="isEdit"         column="is_edit"        />
+		<result property="isList"         column="is_list"        />
+		<result property="isQuery"        column="is_query"       />
+		<result property="queryType"      column="query_type"     />
+		<result property="htmlType"       column="html_type"      />
+		<result property="dictType"       column="dict_type"      />
+		<result property="sort"           column="sort"           />
+		<result property="createBy"       column="create_by"      />
+		<result property="createTime"     column="create_time"    />
+		<result property="updateBy"       column="update_by"      />
+		<result property="updateTime"     column="update_time"    />
+	</resultMap>
+
+	<sql id="selectGenTableVo">
+		select table_id, table_name, table_comment, sub_table_name, sub_table_fk_name, class_name, tpl_category, package_name, module_name, business_name, function_name, function_author, gen_type, gen_path, options, create_by, create_time, update_by, update_time, remark from gen_table
+	</sql>
+
+	<select id="selectGenTableList" parameterType="GenTable" resultMap="GenTableResult">
+		<include refid="selectGenTableVo"/>
+		<where>
+			<if test="tableName != null and tableName != ''">
+				AND lower(table_name) like lower(concat('%', #{tableName}, '%'))
+			</if>
+			<if test="tableComment != null and tableComment != ''">
+				AND lower(table_comment) like lower(concat('%', #{tableComment}, '%'))
+			</if>
+			<if test="params.beginTime != null and params.beginTime != ''"><!-- 寮�濮嬫椂闂存绱� -->
+				<!--				and <![CDATA[ create_time >= convert(datetime, #{params.beginTime}, 20)]]>-->
+				and datediff(d, create_time, #{params.beginTime}) <![CDATA[<=]]> 0
+			</if>
+			<if test="params.endTime != null and params.endTime != ''"><!-- 缁撴潫鏃堕棿妫�绱� -->
+				<!--				and <![CDATA[ create_time <= convert(datetime, #{params.endTime}, 20)]]>-->
+				and datediff(d, create_time, #{params.endTime}) <![CDATA[>=]]> 0
+			</if>
+		</where>
+	</select>
+
+	<select id="selectDbTableList" parameterType="GenTable" resultMap="GenTableResult">
+		SELECT
+		so.name as table_name,
+		sep.value as table_comment,
+		so.create_date as create_time,
+		so.modify_date as update_time
+		FROM
+		sys.objects as so
+		LEFT JOIN sys.extended_properties as sep on so.object_id = sep.major_id
+		WHERE
+		so.type = 'U'
+		AND sep.minor_id = 0
+		AND so.name NOT LIKE 'qrtz_%' AND so.name NOT LIKE 'gen_%'
+		AND so.name NOT LIKE 'act_%'  AND so.name NOT LIKE 'flw_%'
+		AND so.name NOT IN (select table_name from gen_table)
+		<if test="tableName != null and tableName != ''">
+			AND lower(so.name) like lower(concat('%', #{tableName}, '%'))
+		</if>
+		<if test="tableComment != null and tableComment != ''">
+			AND lower(cast(sep.value as nvarchar)) like lower(concat('%', #{tableComment}, '%'))
+		</if>
+		<if test="params.beginTime != null and params.beginTime != ''"><!-- 寮�濮嬫椂闂存绱� -->
+			<!--			and <![CDATA[ create_time >= convert(datetime, #{params.beginTime}, 20)]]>-->
+			and datediff(d, so.create_date, #{params.beginTime}) <![CDATA[<=]]> 0
+		</if>
+		<if test="params.endTime != null and params.endTime != ''"><!-- 缁撴潫鏃堕棿妫�绱� -->
+			<!--			and <![CDATA[ create_time <= convert(datetime, #{params.endTime}, 20)]]>-->
+			and datediff(d, so.create_date, #{params.endTime}) <![CDATA[>=]]> 0
+		</if>
+		order by so.create_date desc
+	</select>
+
+	<select id="selectDbTableListByNames" resultMap="GenTableResult">
+		SELECT
+		SO.name table_name,
+		SEP.VALUE table_comment,
+		SO.create_date create_time,
+		SO.modify_date update_time
+		FROM
+		sys.objects AS SO
+		LEFT JOIN sys.extended_properties AS SEP ON SO.object_id = SEP.major_id
+		WHERE
+		SO.type = 'U'
+		AND SEP.minor_id = 0
+		and SO.name NOT LIKE 'qrtz_%' and SO.name NOT LIKE 'gen_%'
+		AND so.name NOT LIKE 'act_%'  AND so.name NOT LIKE 'flw_%'
+		and SO.name in
+		<foreach collection="array" item="name" open="(" separator="," close=")">
+			#{name}
+		</foreach>
+	</select>
+
+	<select id="selectTableByName" parameterType="String" resultMap="GenTableResult">
+		select table_name, table_comment, create_time, update_time from information_schema.tables
+		where table_comment <![CDATA[ <> ]]> '' and table_schema = (select database())
+		  and table_name = #{tableName}
+	</select>
+
+	<select id="selectGenTableById" parameterType="Long" resultMap="GenTableResult">
+		SELECT t.table_id, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.gen_type, t.gen_path, t.options, t.remark,
+			   c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort
+		FROM gen_table t
+				 LEFT JOIN gen_table_column c ON t.table_id = c.table_id
+		where t.table_id = #{tableId} order by c.sort
+	</select>
+
+	<select id="selectGenTableByName" parameterType="String" resultMap="GenTableResult">
+		SELECT t.table_id, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.gen_type, t.gen_path, t.options, t.remark,
+			   c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort
+		FROM gen_table t
+				 LEFT JOIN gen_table_column c ON t.table_id = c.table_id
+		where t.table_name = #{tableName} order by c.sort
+	</select>
+
+	<select id="selectGenTableAll" parameterType="String" resultMap="GenTableResult">
+		SELECT t.table_id, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.options, t.remark,
+			   c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort
+		FROM gen_table t
+				 LEFT JOIN gen_table_column c ON t.table_id = c.table_id
+		order by c.sort
+	</select>
+
+	<insert id="insertGenTable" parameterType="GenTable" useGeneratedKeys="true" keyProperty="tableId">
+		insert into gen_table (
+		<if test="tableName != null">table_name,</if>
+		<if test="tableComment != null and tableComment != ''">table_comment,</if>
+		<if test="className != null and className != ''">class_name,</if>
+		<if test="tplCategory != null and tplCategory != ''">tpl_category,</if>
+		<if test="packageName != null and packageName != ''">package_name,</if>
+		<if test="moduleName != null and moduleName != ''">module_name,</if>
+		<if test="businessName != null and businessName != ''">business_name,</if>
+		<if test="functionName != null and functionName != ''">function_name,</if>
+		<if test="functionAuthor != null and functionAuthor != ''">function_author,</if>
+		<if test="genType != null and genType != ''">gen_type,</if>
+		<if test="genPath != null and genPath != ''">gen_path,</if>
+		<if test="remark != null and remark != ''">remark,</if>
+		<if test="createBy != null and createBy != ''">create_by,</if>
+		create_time
+		)values(
+		<if test="tableName != null">#{tableName},</if>
+		<if test="tableComment != null and tableComment != ''">#{tableComment},</if>
+		<if test="className != null and className != ''">#{className},</if>
+		<if test="tplCategory != null and tplCategory != ''">#{tplCategory},</if>
+		<if test="packageName != null and packageName != ''">#{packageName},</if>
+		<if test="moduleName != null and moduleName != ''">#{moduleName},</if>
+		<if test="businessName != null and businessName != ''">#{businessName},</if>
+		<if test="functionName != null and functionName != ''">#{functionName},</if>
+		<if test="functionAuthor != null and functionAuthor != ''">#{functionAuthor},</if>
+		<if test="genType != null and genType != ''">#{genType},</if>
+		<if test="genPath != null and genPath != ''">#{genPath},</if>
+		<if test="remark != null and remark != ''">#{remark},</if>
+		<if test="createBy != null and createBy != ''">#{createBy},</if>
+		getdate()
+		)
+	</insert>
+
+	<update id="updateGenTable" parameterType="GenTable">
+		update gen_table
+		<set>
+			<if test="tableName != null">table_name = #{tableName},</if>
+			<if test="tableComment != null and tableComment != ''">table_comment = #{tableComment},</if>
+			<if test="subTableName != null">sub_table_name = #{subTableName},</if>
+			<if test="subTableFkName != null">sub_table_fk_name = #{subTableFkName},</if>
+			<if test="className != null and className != ''">class_name = #{className},</if>
+			<if test="functionAuthor != null and functionAuthor != ''">function_author = #{functionAuthor},</if>
+			<if test="genType != null and genType != ''">gen_type = #{genType},</if>
+			<if test="genPath != null and genPath != ''">gen_path = #{genPath},</if>
+			<if test="tplCategory != null and tplCategory != ''">tpl_category = #{tplCategory},</if>
+			<if test="packageName != null and packageName != ''">package_name = #{packageName},</if>
+			<if test="moduleName != null and moduleName != ''">module_name = #{moduleName},</if>
+			<if test="businessName != null and businessName != ''">business_name = #{businessName},</if>
+			<if test="functionName != null and functionName != ''">function_name = #{functionName},</if>
+			<if test="options != null and options != ''">options = #{options},</if>
+			<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
+			<if test="remark != null">remark = #{remark},</if>
+			update_time = getdate()
+		</set>
+		where table_id = #{tableId}
+	</update>
+
+	<delete id="deleteGenTableByIds" parameterType="Long">
+		delete from gen_table where table_id in
+		<foreach collection="array" item="tableId" open="(" separator="," close=")">
+			#{tableId}
+		</foreach>
+	</delete>
+
+</mapper>
\ No newline at end of file
diff --git a/jcdm-generator/src/main/resources/vm/java/controller.java.vm b/jcdm-generator/src/main/resources/vm/java/controller.java.vm
new file mode 100644
index 0000000..7d1c0ce
--- /dev/null
+++ b/jcdm-generator/src/main/resources/vm/java/controller.java.vm
@@ -0,0 +1,115 @@
+package ${packageName}.controller;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.enums.BusinessType;
+import ${packageName}.domain.${ClassName};
+import ${packageName}.service.I${ClassName}Service;
+import com.jcdm.common.utils.poi.ExcelUtil;
+#if($table.crud || $table.sub)
+import com.jcdm.common.core.page.TableDataInfo;
+#elseif($table.tree)
+#end
+
+/**
+ * ${functionName}Controller
+ * 
+ * @author ${author}
+ * @date ${datetime}
+ */
+@RestController
+@RequestMapping("/${moduleName}/${businessName}")
+public class ${ClassName}Controller extends BaseController
+{
+    @Autowired
+    private I${ClassName}Service ${className}Service;
+
+    /**
+     * 鏌ヨ${functionName}鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('${permissionPrefix}:list')")
+    @GetMapping("/list")
+#if($table.crud || $table.sub)
+    public TableDataInfo list(${ClassName} ${className})
+    {
+        startPage();
+        List<${ClassName}> list = ${className}Service.select${ClassName}List(${className});
+        return getDataTable(list);
+    }
+#elseif($table.tree)
+    public AjaxResult list(${ClassName} ${className})
+    {
+        List<${ClassName}> list = ${className}Service.select${ClassName}List(${className});
+        return success(list);
+    }
+#end
+
+    /**
+     * 瀵煎嚭${functionName}鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('${permissionPrefix}:export')")
+    @Log(title = "${functionName}", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, ${ClassName} ${className})
+    {
+        List<${ClassName}> list = ${className}Service.select${ClassName}List(${className});
+        ExcelUtil<${ClassName}> util = new ExcelUtil<${ClassName}>(${ClassName}.class);
+        util.exportExcel(response, list, "${functionName}鏁版嵁");
+    }
+
+    /**
+     * 鑾峰彇${functionName}璇︾粏淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('${permissionPrefix}:query')")
+    @GetMapping(value = "/{${pkColumn.javaField}}")
+    public AjaxResult getInfo(@PathVariable("${pkColumn.javaField}") ${pkColumn.javaType} ${pkColumn.javaField})
+    {
+        return success(${className}Service.select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaField}));
+    }
+
+    /**
+     * 鏂板${functionName}
+     */
+    @PreAuthorize("@ss.hasPermi('${permissionPrefix}:add')")
+    @Log(title = "${functionName}", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody ${ClassName} ${className})
+    {
+        return toAjax(${className}Service.insert${ClassName}(${className}));
+    }
+
+    /**
+     * 淇敼${functionName}
+     */
+    @PreAuthorize("@ss.hasPermi('${permissionPrefix}:edit')")
+    @Log(title = "${functionName}", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody ${ClassName} ${className})
+    {
+        return toAjax(${className}Service.update${ClassName}(${className}));
+    }
+
+    /**
+     * 鍒犻櫎${functionName}
+     */
+    @PreAuthorize("@ss.hasPermi('${permissionPrefix}:remove')")
+    @Log(title = "${functionName}", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{${pkColumn.javaField}s}")
+    public AjaxResult remove(@PathVariable ${pkColumn.javaType}[] ${pkColumn.javaField}s)
+    {
+        return toAjax(${className}Service.delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaField}s));
+    }
+}
diff --git a/jcdm-generator/src/main/resources/vm/java/domain.java.vm b/jcdm-generator/src/main/resources/vm/java/domain.java.vm
new file mode 100644
index 0000000..e8456fa
--- /dev/null
+++ b/jcdm-generator/src/main/resources/vm/java/domain.java.vm
@@ -0,0 +1,105 @@
+package ${packageName}.domain;
+
+#foreach ($import in $importList)
+import ${import};
+#end
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.jcdm.common.annotation.Excel;
+#if($table.crud || $table.sub)
+import com.jcdm.common.core.domain.BaseEntity;
+#elseif($table.tree)
+import com.jcdm.common.core.domain.TreeEntity;
+#end
+
+/**
+ * ${functionName}瀵硅薄 ${tableName}
+ * 
+ * @author ${author}
+ * @date ${datetime}
+ */
+#if($table.crud || $table.sub)
+#set($Entity="BaseEntity")
+#elseif($table.tree)
+#set($Entity="TreeEntity")
+#end
+public class ${ClassName} extends ${Entity}
+{
+    private static final long serialVersionUID = 1L;
+
+#foreach ($column in $columns)
+#if(!$table.isSuperColumn($column.javaField))
+    /** $column.columnComment */
+#if($column.list)
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($parentheseIndex != -1)
+    @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+#elseif($column.javaType == 'Date')
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "${comment}", width = 30, dateFormat = "yyyy-MM-dd")
+#else
+    @Excel(name = "${comment}")
+#end
+#end
+    private $column.javaType $column.javaField;
+
+#end
+#end
+#if($table.sub)
+    /** $table.subTable.functionName淇℃伅 */
+    private List<${subClassName}> ${subclassName}List;
+
+#end
+#foreach ($column in $columns)
+#if(!$table.isSuperColumn($column.javaField))
+#if($column.javaField.length() > 2 && $column.javaField.substring(1,2).matches("[A-Z]"))
+#set($AttrName=$column.javaField)
+#else
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+#end
+    public void set${AttrName}($column.javaType $column.javaField) 
+    {
+        this.$column.javaField = $column.javaField;
+    }
+
+    public $column.javaType get${AttrName}() 
+    {
+        return $column.javaField;
+    }
+#end
+#end
+
+#if($table.sub)
+    public List<${subClassName}> get${subClassName}List()
+    {
+        return ${subclassName}List;
+    }
+
+    public void set${subClassName}List(List<${subClassName}> ${subclassName}List)
+    {
+        this.${subclassName}List = ${subclassName}List;
+    }
+
+#end
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+#foreach ($column in $columns)
+#if($column.javaField.length() > 2 && $column.javaField.substring(1,2).matches("[A-Z]"))
+#set($AttrName=$column.javaField)
+#else
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+#end
+            .append("${column.javaField}", get${AttrName}())
+#end
+#if($table.sub)
+            .append("${subclassName}List", get${subClassName}List())
+#end
+            .toString();
+    }
+}
diff --git a/jcdm-generator/src/main/resources/vm/java/mapper.java.vm b/jcdm-generator/src/main/resources/vm/java/mapper.java.vm
new file mode 100644
index 0000000..7e7d7c2
--- /dev/null
+++ b/jcdm-generator/src/main/resources/vm/java/mapper.java.vm
@@ -0,0 +1,91 @@
+package ${packageName}.mapper;
+
+import java.util.List;
+import ${packageName}.domain.${ClassName};
+#if($table.sub)
+import ${packageName}.domain.${subClassName};
+#end
+
+/**
+ * ${functionName}Mapper鎺ュ彛
+ * 
+ * @author ${author}
+ * @date ${datetime}
+ */
+public interface ${ClassName}Mapper 
+{
+    /**
+     * 鏌ヨ${functionName}
+     * 
+     * @param ${pkColumn.javaField} ${functionName}涓婚敭
+     * @return ${functionName}
+     */
+    public ${ClassName} select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField});
+
+    /**
+     * 鏌ヨ${functionName}鍒楄〃
+     * 
+     * @param ${className} ${functionName}
+     * @return ${functionName}闆嗗悎
+     */
+    public List<${ClassName}> select${ClassName}List(${ClassName} ${className});
+
+    /**
+     * 鏂板${functionName}
+     * 
+     * @param ${className} ${functionName}
+     * @return 缁撴灉
+     */
+    public int insert${ClassName}(${ClassName} ${className});
+
+    /**
+     * 淇敼${functionName}
+     * 
+     * @param ${className} ${functionName}
+     * @return 缁撴灉
+     */
+    public int update${ClassName}(${ClassName} ${className});
+
+    /**
+     * 鍒犻櫎${functionName}
+     * 
+     * @param ${pkColumn.javaField} ${functionName}涓婚敭
+     * @return 缁撴灉
+     */
+    public int delete${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField});
+
+    /**
+     * 鎵归噺鍒犻櫎${functionName}
+     * 
+     * @param ${pkColumn.javaField}s 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaType}[] ${pkColumn.javaField}s);
+#if($table.sub)
+
+    /**
+     * 鎵归噺鍒犻櫎${subTable.functionName}
+     * 
+     * @param ${pkColumn.javaField}s 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int delete${subClassName}By${subTableFkClassName}s(${pkColumn.javaType}[] ${pkColumn.javaField}s);
+    
+    /**
+     * 鎵归噺鏂板${subTable.functionName}
+     * 
+     * @param ${subclassName}List ${subTable.functionName}鍒楄〃
+     * @return 缁撴灉
+     */
+    public int batch${subClassName}(List<${subClassName}> ${subclassName}List);
+    
+
+    /**
+     * 閫氳繃${functionName}涓婚敭鍒犻櫎${subTable.functionName}淇℃伅
+     * 
+     * @param ${pkColumn.javaField} ${functionName}ID
+     * @return 缁撴灉
+     */
+    public int delete${subClassName}By${subTableFkClassName}(${pkColumn.javaType} ${pkColumn.javaField});
+#end
+}
diff --git a/jcdm-generator/src/main/resources/vm/java/service.java.vm b/jcdm-generator/src/main/resources/vm/java/service.java.vm
new file mode 100644
index 0000000..264882b
--- /dev/null
+++ b/jcdm-generator/src/main/resources/vm/java/service.java.vm
@@ -0,0 +1,61 @@
+package ${packageName}.service;
+
+import java.util.List;
+import ${packageName}.domain.${ClassName};
+
+/**
+ * ${functionName}Service鎺ュ彛
+ * 
+ * @author ${author}
+ * @date ${datetime}
+ */
+public interface I${ClassName}Service 
+{
+    /**
+     * 鏌ヨ${functionName}
+     * 
+     * @param ${pkColumn.javaField} ${functionName}涓婚敭
+     * @return ${functionName}
+     */
+    public ${ClassName} select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField});
+
+    /**
+     * 鏌ヨ${functionName}鍒楄〃
+     * 
+     * @param ${className} ${functionName}
+     * @return ${functionName}闆嗗悎
+     */
+    public List<${ClassName}> select${ClassName}List(${ClassName} ${className});
+
+    /**
+     * 鏂板${functionName}
+     * 
+     * @param ${className} ${functionName}
+     * @return 缁撴灉
+     */
+    public int insert${ClassName}(${ClassName} ${className});
+
+    /**
+     * 淇敼${functionName}
+     * 
+     * @param ${className} ${functionName}
+     * @return 缁撴灉
+     */
+    public int update${ClassName}(${ClassName} ${className});
+
+    /**
+     * 鎵归噺鍒犻櫎${functionName}
+     * 
+     * @param ${pkColumn.javaField}s 闇�瑕佸垹闄ょ殑${functionName}涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaType}[] ${pkColumn.javaField}s);
+
+    /**
+     * 鍒犻櫎${functionName}淇℃伅
+     * 
+     * @param ${pkColumn.javaField} ${functionName}涓婚敭
+     * @return 缁撴灉
+     */
+    public int delete${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField});
+}
diff --git a/jcdm-generator/src/main/resources/vm/java/serviceImpl.java.vm b/jcdm-generator/src/main/resources/vm/java/serviceImpl.java.vm
new file mode 100644
index 0000000..00ffced
--- /dev/null
+++ b/jcdm-generator/src/main/resources/vm/java/serviceImpl.java.vm
@@ -0,0 +1,169 @@
+package ${packageName}.service.impl;
+
+import java.util.List;
+#foreach ($column in $columns)
+#if($column.javaField == 'createTime' || $column.javaField == 'updateTime')
+import com.jcdm.common.utils.DateUtils;
+#break
+#end
+#end
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+#if($table.sub)
+import java.util.ArrayList;
+import com.jcdm.common.utils.StringUtils;
+import org.springframework.transaction.annotation.Transactional;
+import ${packageName}.domain.${subClassName};
+#end
+import ${packageName}.mapper.${ClassName}Mapper;
+import ${packageName}.domain.${ClassName};
+import ${packageName}.service.I${ClassName}Service;
+
+/**
+ * ${functionName}Service涓氬姟灞傚鐞�
+ * 
+ * @author ${author}
+ * @date ${datetime}
+ */
+@Service
+public class ${ClassName}ServiceImpl implements I${ClassName}Service 
+{
+    @Autowired
+    private ${ClassName}Mapper ${className}Mapper;
+
+    /**
+     * 鏌ヨ${functionName}
+     * 
+     * @param ${pkColumn.javaField} ${functionName}涓婚敭
+     * @return ${functionName}
+     */
+    @Override
+    public ${ClassName} select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField})
+    {
+        return ${className}Mapper.select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaField});
+    }
+
+    /**
+     * 鏌ヨ${functionName}鍒楄〃
+     * 
+     * @param ${className} ${functionName}
+     * @return ${functionName}
+     */
+    @Override
+    public List<${ClassName}> select${ClassName}List(${ClassName} ${className})
+    {
+        return ${className}Mapper.select${ClassName}List(${className});
+    }
+
+    /**
+     * 鏂板${functionName}
+     * 
+     * @param ${className} ${functionName}
+     * @return 缁撴灉
+     */
+#if($table.sub)
+    @Transactional
+#end
+    @Override
+    public int insert${ClassName}(${ClassName} ${className})
+    {
+#foreach ($column in $columns)
+#if($column.javaField == 'createTime')
+        ${className}.setCreateTime(DateUtils.getNowDate());
+#end
+#end
+#if($table.sub)
+        int rows = ${className}Mapper.insert${ClassName}(${className});
+        insert${subClassName}(${className});
+        return rows;
+#else
+        return ${className}Mapper.insert${ClassName}(${className});
+#end
+    }
+
+    /**
+     * 淇敼${functionName}
+     * 
+     * @param ${className} ${functionName}
+     * @return 缁撴灉
+     */
+#if($table.sub)
+    @Transactional
+#end
+    @Override
+    public int update${ClassName}(${ClassName} ${className})
+    {
+#foreach ($column in $columns)
+#if($column.javaField == 'updateTime')
+        ${className}.setUpdateTime(DateUtils.getNowDate());
+#end
+#end
+#if($table.sub)
+        ${className}Mapper.delete${subClassName}By${subTableFkClassName}(${className}.get${pkColumn.capJavaField}());
+        insert${subClassName}(${className});
+#end
+        return ${className}Mapper.update${ClassName}(${className});
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎${functionName}
+     * 
+     * @param ${pkColumn.javaField}s 闇�瑕佸垹闄ょ殑${functionName}涓婚敭
+     * @return 缁撴灉
+     */
+#if($table.sub)
+    @Transactional
+#end
+    @Override
+    public int delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaType}[] ${pkColumn.javaField}s)
+    {
+#if($table.sub)
+        ${className}Mapper.delete${subClassName}By${subTableFkClassName}s(${pkColumn.javaField}s);
+#end
+        return ${className}Mapper.delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaField}s);
+    }
+
+    /**
+     * 鍒犻櫎${functionName}淇℃伅
+     * 
+     * @param ${pkColumn.javaField} ${functionName}涓婚敭
+     * @return 缁撴灉
+     */
+#if($table.sub)
+    @Transactional
+#end
+    @Override
+    public int delete${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField})
+    {
+#if($table.sub)
+        ${className}Mapper.delete${subClassName}By${subTableFkClassName}(${pkColumn.javaField});
+#end
+        return ${className}Mapper.delete${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaField});
+    }
+#if($table.sub)
+
+    /**
+     * 鏂板${subTable.functionName}淇℃伅
+     * 
+     * @param ${className} ${functionName}瀵硅薄
+     */
+    public void insert${subClassName}(${ClassName} ${className})
+    {
+        List<${subClassName}> ${subclassName}List = ${className}.get${subClassName}List();
+        ${pkColumn.javaType} ${pkColumn.javaField} = ${className}.get${pkColumn.capJavaField}();
+        if (StringUtils.isNotNull(${subclassName}List))
+        {
+            List<${subClassName}> list = new ArrayList<${subClassName}>();
+            for (${subClassName} ${subclassName} : ${subclassName}List)
+            {
+                ${subclassName}.set${subTableFkClassName}(${pkColumn.javaField});
+                list.add(${subclassName});
+            }
+            if (list.size() > 0)
+            {
+                ${className}Mapper.batch${subClassName}(list);
+            }
+        }
+    }
+#end
+}
diff --git a/jcdm-generator/src/main/resources/vm/java/sub-domain.java.vm b/jcdm-generator/src/main/resources/vm/java/sub-domain.java.vm
new file mode 100644
index 0000000..91f91d7
--- /dev/null
+++ b/jcdm-generator/src/main/resources/vm/java/sub-domain.java.vm
@@ -0,0 +1,76 @@
+package ${packageName}.domain;
+
+#foreach ($import in $subImportList)
+import ${import};
+#end
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.core.domain.BaseEntity;
+
+/**
+ * ${subTable.functionName}瀵硅薄 ${subTableName}
+ * 
+ * @author ${author}
+ * @date ${datetime}
+ */
+public class ${subClassName} extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+#foreach ($column in $subTable.columns)
+#if(!$table.isSuperColumn($column.javaField))
+    /** $column.columnComment */
+#if($column.list)
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($parentheseIndex != -1)
+    @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+#elseif($column.javaType == 'Date')
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "${comment}", width = 30, dateFormat = "yyyy-MM-dd")
+#else
+    @Excel(name = "${comment}")
+#end
+#end
+    private $column.javaType $column.javaField;
+
+#end
+#end
+#foreach ($column in $subTable.columns)
+#if(!$table.isSuperColumn($column.javaField))
+#if($column.javaField.length() > 2 && $column.javaField.substring(1,2).matches("[A-Z]"))
+#set($AttrName=$column.javaField)
+#else
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+#end
+    public void set${AttrName}($column.javaType $column.javaField) 
+    {
+        this.$column.javaField = $column.javaField;
+    }
+
+    public $column.javaType get${AttrName}() 
+    {
+        return $column.javaField;
+    }
+#end
+#end
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+#foreach ($column in $subTable.columns)
+#if($column.javaField.length() > 2 && $column.javaField.substring(1,2).matches("[A-Z]"))
+#set($AttrName=$column.javaField)
+#else
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+#end
+            .append("${column.javaField}", get${AttrName}())
+#end
+            .toString();
+    }
+}
diff --git a/jcdm-generator/src/main/resources/vm/js/api.js.vm b/jcdm-generator/src/main/resources/vm/js/api.js.vm
new file mode 100644
index 0000000..9295524
--- /dev/null
+++ b/jcdm-generator/src/main/resources/vm/js/api.js.vm
@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 鏌ヨ${functionName}鍒楄〃
+export function list${BusinessName}(query) {
+  return request({
+    url: '/${moduleName}/${businessName}/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ${functionName}璇︾粏
+export function get${BusinessName}(${pkColumn.javaField}) {
+  return request({
+    url: '/${moduleName}/${businessName}/' + ${pkColumn.javaField},
+    method: 'get'
+  })
+}
+
+// 鏂板${functionName}
+export function add${BusinessName}(data) {
+  return request({
+    url: '/${moduleName}/${businessName}',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼${functionName}
+export function update${BusinessName}(data) {
+  return request({
+    url: '/${moduleName}/${businessName}',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎${functionName}
+export function del${BusinessName}(${pkColumn.javaField}) {
+  return request({
+    url: '/${moduleName}/${businessName}/' + ${pkColumn.javaField},
+    method: 'delete'
+  })
+}
diff --git a/jcdm-generator/src/main/resources/vm/sql/sql.vm b/jcdm-generator/src/main/resources/vm/sql/sql.vm
new file mode 100644
index 0000000..ac226a9
--- /dev/null
+++ b/jcdm-generator/src/main/resources/vm/sql/sql.vm
@@ -0,0 +1,23 @@
+-- 鑿滃崟 SQL
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('${functionName}', '${parentMenuId}', '1', '${businessName}', '${moduleName}/${businessName}/index', 1, 0, 'C', '0', '0', '${permissionPrefix}:list', '#', 'admin', getdate(), '', null, '${functionName}鑿滃崟');
+
+-- 鎸夐挳鐖惰彍鍗旾D
+DECLARE @parentId bigint
+select @parentId=max(menu_id) from sys_menu
+
+-- 鎸夐挳 SQL
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('${functionName}鏌ヨ', @parentId, '1',  '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:query',        '#', 'admin', getdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('${functionName}鏂板', @parentId, '2',  '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:add',          '#', 'admin', getdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('${functionName}淇敼', @parentId, '3',  '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:edit',         '#', 'admin', getdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('${functionName}鍒犻櫎', @parentId, '4',  '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:remove',       '#', 'admin', getdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('${functionName}瀵煎嚭', @parentId, '5',  '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:export',       '#', 'admin', getdate(), '', null, '');
\ No newline at end of file
diff --git a/jcdm-generator/src/main/resources/vm/vue/index-tree.vue.vm b/jcdm-generator/src/main/resources/vm/vue/index-tree.vue.vm
new file mode 100644
index 0000000..4819c2a
--- /dev/null
+++ b/jcdm-generator/src/main/resources/vm/vue/index-tree.vue.vm
@@ -0,0 +1,505 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+#foreach($column in $columns)
+#if($column.query)
+#set($dictType=$column.dictType)
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($column.htmlType == "input")
+      <el-form-item label="${comment}" prop="${column.javaField}">
+        <el-input
+          v-model="queryParams.${column.javaField}"
+          placeholder="璇疯緭鍏�${comment}"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && "" != $dictType)
+      <el-form-item label="${comment}" prop="${column.javaField}">
+        <el-select v-model="queryParams.${column.javaField}" placeholder="璇烽�夋嫨${comment}" clearable>
+          <el-option
+            v-for="dict in dict.type.${dictType}"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && $dictType)
+      <el-form-item label="${comment}" prop="${column.javaField}">
+        <el-select v-model="queryParams.${column.javaField}" placeholder="璇烽�夋嫨${comment}" clearable>
+          <el-option label="璇烽�夋嫨瀛楀吀鐢熸垚" value="" />
+        </el-select>
+      </el-form-item>
+#elseif($column.htmlType == "datetime" && $column.queryType != "BETWEEN")
+      <el-form-item label="${comment}" prop="${column.javaField}">
+        <el-date-picker clearable
+          v-model="queryParams.${column.javaField}"
+          type="date"
+          value-format="yyyy-MM-dd"
+          placeholder="閫夋嫨${comment}">
+        </el-date-picker>
+      </el-form-item>
+#elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+      <el-form-item label="${comment}">
+        <el-date-picker
+          v-model="daterange${AttrName}"
+          style="width: 240px"
+          value-format="yyyy-MM-dd"
+          type="daterange"
+          range-separator="-"
+          start-placeholder="寮�濮嬫棩鏈�"
+          end-placeholder="缁撴潫鏃ユ湡"
+        ></el-date-picker>
+      </el-form-item>
+#end
+#end
+#end
+      <el-form-item>
+	    <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['${moduleName}:${businessName}:add']"
+        >鏂板</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="info"
+          plain
+          icon="el-icon-sort"
+          size="mini"
+          @click="toggleExpandAll"
+        >灞曞紑/鎶樺彔</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table
+      v-if="refreshTable"
+      v-loading="loading"
+      :data="${businessName}List"
+      row-key="${treeCode}"
+      :default-expand-all="isExpandAll"
+      :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
+    >
+#foreach($column in $columns)
+#set($javaField=$column.javaField)
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($column.pk)
+#elseif($column.list && $column.htmlType == "datetime")
+      <el-table-column label="${comment}" align="center" prop="${javaField}" width="180">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.${javaField}, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+#elseif($column.list && $column.htmlType == "imageUpload")
+      <el-table-column label="${comment}" align="center" prop="${javaField}" width="100">
+        <template slot-scope="scope">
+          <image-preview :src="scope.row.${javaField}" :width="50" :height="50"/>
+        </template>
+      </el-table-column>
+#elseif($column.list && "" != $column.dictType)
+      <el-table-column label="${comment}" align="center" prop="${javaField}">
+        <template slot-scope="scope">
+#if($column.htmlType == "checkbox")
+          <dict-tag :options="dict.type.${column.dictType}" :value="scope.row.${javaField} ? scope.row.${javaField}.split(',') : []"/>
+#else
+          <dict-tag :options="dict.type.${column.dictType}" :value="scope.row.${javaField}"/>
+#end
+        </template>
+      </el-table-column>
+#elseif($column.list && "" != $javaField)
+#if(${foreach.index} == 1)
+      <el-table-column label="${comment}" prop="${javaField}" />
+#else
+      <el-table-column label="${comment}" align="center" prop="${javaField}" />
+#end
+#end
+#end
+      <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['${moduleName}:${businessName}:edit']"
+          >淇敼</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-plus"
+            @click="handleAdd(scope.row)"
+            v-hasPermi="['${moduleName}:${businessName}:add']"
+          >鏂板</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['${moduleName}:${businessName}:remove']"
+          >鍒犻櫎</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- 娣诲姞鎴栦慨鏀�${functionName}瀵硅瘽妗� -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+#foreach($column in $columns)
+#set($field=$column.javaField)
+#if($column.insert && !$column.pk)
+#if(($column.usableColumn) || (!$column.superColumn))
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#set($dictType=$column.dictType)
+#if("" != $treeParentCode && $column.javaField == $treeParentCode)
+        <el-form-item label="${comment}" prop="${treeParentCode}">
+          <treeselect v-model="form.${treeParentCode}" :options="${businessName}Options" :normalizer="normalizer" placeholder="璇烽�夋嫨${comment}" />
+        </el-form-item>
+#elseif($column.htmlType == "input")
+        <el-form-item label="${comment}" prop="${field}">
+          <el-input v-model="form.${field}" placeholder="璇疯緭鍏�${comment}" />
+        </el-form-item>
+#elseif($column.htmlType == "imageUpload")
+        <el-form-item label="${comment}" prop="${field}">
+          <image-upload v-model="form.${field}"/>
+        </el-form-item>
+#elseif($column.htmlType == "fileUpload")
+        <el-form-item label="${comment}" prop="${field}">
+          <file-upload v-model="form.${field}"/>
+        </el-form-item>
+#elseif($column.htmlType == "editor")
+        <el-form-item label="${comment}">
+          <editor v-model="form.${field}" :min-height="192"/>
+        </el-form-item>
+#elseif($column.htmlType == "select" && "" != $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-select v-model="form.${field}" placeholder="璇烽�夋嫨${comment}">
+            <el-option
+              v-for="dict in dict.type.${dictType}"
+              :key="dict.value"
+              :label="dict.label"
+#if($column.javaType == "Integer" || $column.javaType == "Long")
+              :value="parseInt(dict.value)"
+#else
+              :value="dict.value"
+#end
+            ></el-option>
+          </el-select>
+        </el-form-item>
+#elseif($column.htmlType == "select" && $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-select v-model="form.${field}" placeholder="璇烽�夋嫨${comment}">
+            <el-option label="璇烽�夋嫨瀛楀吀鐢熸垚" value="" />
+          </el-select>
+        </el-form-item>
+#elseif($column.htmlType == "checkbox" && "" != $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-checkbox-group v-model="form.${field}">
+            <el-checkbox
+              v-for="dict in dict.type.${dictType}"
+              :key="dict.value"
+              :label="dict.value">
+              {{dict.label}}
+            </el-checkbox>
+          </el-checkbox-group>
+        </el-form-item>
+#elseif($column.htmlType == "checkbox" && $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-checkbox-group v-model="form.${field}">
+            <el-checkbox>璇烽�夋嫨瀛楀吀鐢熸垚</el-checkbox>
+          </el-checkbox-group>
+        </el-form-item>
+#elseif($column.htmlType == "radio" && "" != $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-radio-group v-model="form.${field}">
+            <el-radio
+              v-for="dict in dict.type.${dictType}"
+              :key="dict.value"
+#if($column.javaType == "Integer" || $column.javaType == "Long")
+              :label="parseInt(dict.value)"
+#else
+              :label="dict.value"
+#end
+            >{{dict.label}}</el-radio>
+          </el-radio-group>
+        </el-form-item>
+#elseif($column.htmlType == "radio" && $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-radio-group v-model="form.${field}">
+            <el-radio label="1">璇烽�夋嫨瀛楀吀鐢熸垚</el-radio>
+          </el-radio-group>
+        </el-form-item>
+#elseif($column.htmlType == "datetime")
+        <el-form-item label="${comment}" prop="${field}">
+          <el-date-picker clearable
+            v-model="form.${field}"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="閫夋嫨${comment}">
+          </el-date-picker>
+        </el-form-item>
+#elseif($column.htmlType == "textarea")
+        <el-form-item label="${comment}" prop="${field}">
+          <el-input v-model="form.${field}" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
+        </el-form-item>
+#end
+#end
+#end
+#end
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+
+export default {
+  name: "${BusinessName}",
+#if(${dicts} != '')
+  dicts: [${dicts}],
+#end
+  components: {
+    Treeselect
+  },
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // ${functionName}琛ㄦ牸鏁版嵁
+      ${businessName}List: [],
+      // ${functionName}鏍戦�夐」
+      ${businessName}Options: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏄惁灞曞紑锛岄粯璁ゅ叏閮ㄥ睍寮�
+      isExpandAll: true,
+      // 閲嶆柊娓叉煋琛ㄦ牸鐘舵��
+      refreshTable: true,
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+      // $comment鏃堕棿鑼冨洿
+      daterange${AttrName}: [],
+#end
+#end
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+#foreach ($column in $columns)
+#if($column.query)
+        $column.javaField: null#if($foreach.count != $columns.size()),#end
+#end
+#end
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+#foreach ($column in $columns)
+#if($column.required)
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+        $column.javaField: [
+          { required: true, message: "$comment涓嶈兘涓虹┖", trigger: #if($column.htmlType == "select" || $column.htmlType == "radio")"change"#else"blur"#end }
+        ]#if($foreach.count != $columns.size()),#end
+#end
+#end
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 鏌ヨ${functionName}鍒楄〃 */
+    getList() {
+      this.loading = true;
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+      this.queryParams.params = {};
+#break
+#end
+#end
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+      if (null != this.daterange${AttrName} && '' != this.daterange${AttrName}) {
+        this.queryParams.params["begin${AttrName}"] = this.daterange${AttrName}[0];
+        this.queryParams.params["end${AttrName}"] = this.daterange${AttrName}[1];
+      }
+#end
+#end
+      list${BusinessName}(this.queryParams).then(response => {
+        this.${businessName}List = this.handleTree(response.data, "${treeCode}", "${treeParentCode}");
+        this.loading = false;
+      });
+    },
+    /** 杞崲${functionName}鏁版嵁缁撴瀯 */
+    normalizer(node) {
+      if (node.children && !node.children.length) {
+        delete node.children;
+      }
+      return {
+        id: node.${treeCode},
+        label: node.${treeName},
+        children: node.children
+      };
+    },
+	/** 鏌ヨ${functionName}涓嬫媺鏍戠粨鏋� */
+    getTreeselect() {
+      list${BusinessName}().then(response => {
+        this.${businessName}Options = [];
+        const data = { ${treeCode}: 0, ${treeName}: '椤剁骇鑺傜偣', children: [] };
+        data.children = this.handleTree(response.data, "${treeCode}", "${treeParentCode}");
+        this.${businessName}Options.push(data);
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+#foreach ($column in $columns)
+#if($column.htmlType == "checkbox")
+        $column.javaField: []#if($foreach.count != $columns.size()),#end
+#else
+        $column.javaField: null#if($foreach.count != $columns.size()),#end
+#end
+#end
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+      this.daterange${AttrName} = [];
+#end
+#end
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd(row) {
+      this.reset();
+      this.getTreeselect();
+      if (row != null && row.${treeCode}) {
+        this.form.${treeParentCode} = row.${treeCode};
+      } else {
+        this.form.${treeParentCode} = 0;
+      }
+      this.open = true;
+      this.title = "娣诲姞${functionName}";
+    },
+    /** 灞曞紑/鎶樺彔鎿嶄綔 */
+    toggleExpandAll() {
+      this.refreshTable = false;
+      this.isExpandAll = !this.isExpandAll;
+      this.$nextTick(() => {
+        this.refreshTable = true;
+      });
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.reset();
+      this.getTreeselect();
+      if (row != null) {
+        this.form.${treeParentCode} = row.${treeParentCode};
+      }
+      get${BusinessName}(row.${pkColumn.javaField}).then(response => {
+        this.form = response.data;
+#foreach ($column in $columns)
+#if($column.htmlType == "checkbox")
+        this.form.$column.javaField = this.form.${column.javaField}.split(",");
+#end
+#end
+        this.open = true;
+        this.title = "淇敼${functionName}";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm() {
+      this.#[[$]]#refs["form"].validate(valid => {
+        if (valid) {
+#foreach ($column in $columns)
+#if($column.htmlType == "checkbox")
+          this.form.$column.javaField = this.form.${column.javaField}.join(",");
+#end
+#end
+          if (this.form.${pkColumn.javaField} != null) {
+            update${BusinessName}(this.form).then(response => {
+              this.#[[$modal]]#.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            add${BusinessName}(this.form).then(response => {
+              this.#[[$modal]]#.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      this.#[[$modal]]#.confirm('鏄惁纭鍒犻櫎${functionName}缂栧彿涓�"' + row.${pkColumn.javaField} + '"鐨勬暟鎹」锛�').then(function() {
+        return del${BusinessName}(row.${pkColumn.javaField});
+      }).then(() => {
+        this.getList();
+        this.#[[$modal]]#.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    }
+  }
+};
+</script>
diff --git a/jcdm-generator/src/main/resources/vm/vue/index.vue.vm b/jcdm-generator/src/main/resources/vm/vue/index.vue.vm
new file mode 100644
index 0000000..9784fd8
--- /dev/null
+++ b/jcdm-generator/src/main/resources/vm/vue/index.vue.vm
@@ -0,0 +1,615 @@
+<template>
+  <div class="app-container">
+    <el-card class="box-card">
+        <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+    #foreach($column in $columns)
+    #if($column.query)
+    #set($dictType=$column.dictType)
+    #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+    #set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+    #if($parentheseIndex != -1)
+    #set($comment=$column.columnComment.substring(0, $parentheseIndex))
+    #else
+    #set($comment=$column.columnComment)
+    #end
+    #if($column.htmlType == "input")
+          <el-form-item label="${comment}" prop="${column.javaField}">
+            <el-input
+              v-model="queryParams.${column.javaField}"
+              placeholder="璇疯緭鍏�${comment}"
+              clearable
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+    #elseif(($column.htmlType == "select" || $column.htmlType == "radio") && "" != $dictType)
+          <el-form-item label="${comment}" prop="${column.javaField}">
+            <el-select v-model="queryParams.${column.javaField}" placeholder="璇烽�夋嫨${comment}" clearable>
+              <el-option
+                v-for="dict in dict.type.${dictType}"
+                :key="dict.value"
+                :label="dict.label"
+                :value="dict.value"
+              />
+            </el-select>
+          </el-form-item>
+    #elseif(($column.htmlType == "select" || $column.htmlType == "radio") && $dictType)
+          <el-form-item label="${comment}" prop="${column.javaField}">
+            <el-select v-model="queryParams.${column.javaField}" placeholder="璇烽�夋嫨${comment}" clearable>
+              <el-option label="璇烽�夋嫨瀛楀吀鐢熸垚" value="" />
+            </el-select>
+          </el-form-item>
+    #elseif($column.htmlType == "datetime" && $column.queryType != "BETWEEN")
+          <el-form-item label="${comment}" prop="${column.javaField}">
+            <el-date-picker clearable
+              v-model="queryParams.${column.javaField}"
+              type="date"
+              value-format="yyyy-MM-dd"
+              placeholder="璇烽�夋嫨${comment}">
+            </el-date-picker>
+          </el-form-item>
+    #elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+          <el-form-item label="${comment}">
+            <el-date-picker
+              v-model="daterange${AttrName}"
+              style="width: 240px"
+              value-format="yyyy-MM-dd"
+              type="daterange"
+              range-separator="-"
+              start-placeholder="寮�濮嬫棩鏈�"
+              end-placeholder="缁撴潫鏃ユ湡"
+            ></el-date-picker>
+          </el-form-item>
+    #end
+    #end
+    #end
+          <el-form-item style="float: right">
+            <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+            <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+          </el-form-item>
+        </el-form>
+    </el-card>
+
+    <el-card style="margin-top: 10px" class="box-card">
+        <el-row :gutter="10" class="mb8">
+          <el-col :span="1.5">
+            <el-button
+              type="primary"
+              plain
+              icon="el-icon-plus"
+              size="mini"
+              @click="handleAdd"
+              v-hasPermi="['${moduleName}:${businessName}:add']"
+            >鏂板</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="success"
+              plain
+              icon="el-icon-edit"
+              size="mini"
+              :disabled="single"
+              @click="handleUpdate"
+              v-hasPermi="['${moduleName}:${businessName}:edit']"
+            >淇敼</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="danger"
+              plain
+              icon="el-icon-delete"
+              size="mini"
+              :disabled="multiple"
+              @click="handleDelete"
+              v-hasPermi="['${moduleName}:${businessName}:remove']"
+            >鍒犻櫎</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="warning"
+              plain
+              icon="el-icon-download"
+              size="mini"
+              @click="handleExport"
+              v-hasPermi="['${moduleName}:${businessName}:export']"
+            >瀵煎嚭</el-button>
+          </el-col>
+          <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+        </el-row>
+
+        <el-table border v-loading="loading" :data="${businessName}List" @selection-change="handleSelectionChange">
+          <el-table-column type="selection" width="55" align="center" />
+    #foreach($column in $columns)
+    #set($javaField=$column.javaField)
+    #set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+    #if($parentheseIndex != -1)
+    #set($comment=$column.columnComment.substring(0, $parentheseIndex))
+    #else
+    #set($comment=$column.columnComment)
+    #end
+    #if($column.pk)
+          <el-table-column label="${comment}" align="center" prop="${javaField}" />
+    #elseif($column.list && $column.htmlType == "datetime")
+          <el-table-column label="${comment}" align="center" prop="${javaField}" width="180">
+            <template slot-scope="scope">
+              <span>{{ parseTime(scope.row.${javaField}, '{y}-{m}-{d}') }}</span>
+            </template>
+          </el-table-column>
+    #elseif($column.list && $column.htmlType == "imageUpload")
+          <el-table-column label="${comment}" align="center" prop="${javaField}" width="100">
+            <template slot-scope="scope">
+              <image-preview :src="scope.row.${javaField}" :width="50" :height="50"/>
+            </template>
+          </el-table-column>
+    #elseif($column.list && "" != $column.dictType)
+          <el-table-column label="${comment}" align="center" prop="${javaField}">
+            <template slot-scope="scope">
+    #if($column.htmlType == "checkbox")
+              <dict-tag :options="dict.type.${column.dictType}" :value="scope.row.${javaField} ? scope.row.${javaField}.split(',') : []"/>
+    #else
+              <dict-tag :options="dict.type.${column.dictType}" :value="scope.row.${javaField}"/>
+    #end
+            </template>
+          </el-table-column>
+    #elseif($column.list && "" != $javaField)
+          <el-table-column label="${comment}" align="center" prop="${javaField}" />
+    #end
+    #end
+          <el-table-column fixed="right" width="200" label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+            <template slot-scope="scope">
+              <el-button
+                size="mini"
+                type="success"
+                plain
+                style="width: 72px"
+                icon="el-icon-edit"
+                @click="handleUpdate(scope.row)"
+                v-hasPermi="['${moduleName}:${businessName}:edit']"
+              >淇敼</el-button>
+              <el-button
+                size="mini"
+                type="danger"
+                plain
+                style="width: 72px"
+                icon="el-icon-delete"
+                @click="handleDelete(scope.row)"
+                v-hasPermi="['${moduleName}:${businessName}:remove']"
+              >鍒犻櫎</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+    </el-card>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 娣诲姞鎴栦慨鏀�${functionName}瀵硅瘽妗� -->
+    <el-dialog v-dialogpop-up :title="title" :visible.sync="open" width="500px" append-to-body>
+      <span slot="title">
+        <i class="el-icon-s-order"></i>
+        {{titleName}}
+      </span>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+#foreach($column in $columns)
+#set($field=$column.javaField)
+#if($column.insert && !$column.pk)
+#if(($column.usableColumn) || (!$column.superColumn))
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#set($dictType=$column.dictType)
+#if($column.htmlType == "input")
+        <el-form-item label="${comment}" prop="${field}">
+          <el-input v-model="form.${field}" placeholder="璇疯緭鍏�${comment}" />
+        </el-form-item>
+#elseif($column.htmlType == "imageUpload")
+        <el-form-item label="${comment}" prop="${field}">
+          <image-upload v-model="form.${field}"/>
+        </el-form-item>
+#elseif($column.htmlType == "fileUpload")
+        <el-form-item label="${comment}" prop="${field}">
+          <file-upload v-model="form.${field}"/>
+        </el-form-item>
+#elseif($column.htmlType == "editor")
+        <el-form-item label="${comment}">
+          <editor v-model="form.${field}" :min-height="192"/>
+        </el-form-item>
+#elseif($column.htmlType == "select" && "" != $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-select v-model="form.${field}" placeholder="璇烽�夋嫨${comment}">
+            <el-option
+              v-for="dict in dict.type.${dictType}"
+              :key="dict.value"
+              :label="dict.label"
+#if($column.javaType == "Integer" || $column.javaType == "Long")
+              :value="parseInt(dict.value)"
+#else
+              :value="dict.value"
+#end
+            ></el-option>
+          </el-select>
+        </el-form-item>
+#elseif($column.htmlType == "select" && $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-select v-model="form.${field}" placeholder="璇烽�夋嫨${comment}">
+            <el-option label="璇烽�夋嫨瀛楀吀鐢熸垚" value="" />
+          </el-select>
+        </el-form-item>
+#elseif($column.htmlType == "checkbox" && "" != $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-checkbox-group v-model="form.${field}">
+            <el-checkbox
+              v-for="dict in dict.type.${dictType}"
+              :key="dict.value"
+              :label="dict.value">
+              {{dict.label}}
+            </el-checkbox>
+          </el-checkbox-group>
+        </el-form-item>
+#elseif($column.htmlType == "checkbox" && $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-checkbox-group v-model="form.${field}">
+            <el-checkbox>璇烽�夋嫨瀛楀吀鐢熸垚</el-checkbox>
+          </el-checkbox-group>
+        </el-form-item>
+#elseif($column.htmlType == "radio" && "" != $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-radio-group v-model="form.${field}">
+            <el-radio
+              v-for="dict in dict.type.${dictType}"
+              :key="dict.value"
+#if($column.javaType == "Integer" || $column.javaType == "Long")
+              :label="parseInt(dict.value)"
+#else
+              :label="dict.value"
+#end
+            >{{dict.label}}</el-radio>
+          </el-radio-group>
+        </el-form-item>
+#elseif($column.htmlType == "radio" && $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-radio-group v-model="form.${field}">
+            <el-radio label="1">璇烽�夋嫨瀛楀吀鐢熸垚</el-radio>
+          </el-radio-group>
+        </el-form-item>
+#elseif($column.htmlType == "datetime")
+        <el-form-item label="${comment}" prop="${field}">
+          <el-date-picker clearable
+            v-model="form.${field}"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="璇烽�夋嫨${comment}">
+          </el-date-picker>
+        </el-form-item>
+#elseif($column.htmlType == "textarea")
+        <el-form-item label="${comment}" prop="${field}">
+          <el-input v-model="form.${field}" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
+        </el-form-item>
+#end
+#end
+#end
+#end
+#if($table.sub)
+        <el-divider content-position="center">${subTable.functionName}淇℃伅</el-divider>
+        <el-row :gutter="10" class="mb8">
+          <el-col :span="1.5">
+            <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd${subClassName}">娣诲姞</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button type="danger" icon="el-icon-delete" size="mini" @click="handleDelete${subClassName}">鍒犻櫎</el-button>
+          </el-col>
+        </el-row>
+        <el-table :data="${subclassName}List" :row-class-name="row${subClassName}Index" @selection-change="handle${subClassName}SelectionChange" ref="${subclassName}">
+          <el-table-column type="selection" width="50" align="center" />
+          <el-table-column label="搴忓彿" align="center" prop="index" width="50"/>
+#foreach($column in $subTable.columns)
+#set($javaField=$column.javaField)
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($column.pk || $javaField == ${subTableFkclassName})
+#elseif($column.list && $column.htmlType == "input")
+          <el-table-column label="$comment" prop="${javaField}" width="150">
+            <template slot-scope="scope">
+              <el-input v-model="scope.row.$javaField" placeholder="璇疯緭鍏�$comment" />
+            </template>
+          </el-table-column>
+#elseif($column.list && $column.htmlType == "datetime")
+          <el-table-column label="$comment" prop="${javaField}" width="240">
+            <template slot-scope="scope">
+              <el-date-picker clearable v-model="scope.row.$javaField" type="date" value-format="yyyy-MM-dd" placeholder="璇烽�夋嫨$comment" />
+            </template>
+          </el-table-column>
+#elseif($column.list && ($column.htmlType == "select" || $column.htmlType == "radio") && "" != $column.dictType)
+          <el-table-column label="$comment" prop="${javaField}" width="150">
+            <template slot-scope="scope">
+              <el-select v-model="scope.row.$javaField" placeholder="璇烽�夋嫨$comment">
+                <el-option
+                  v-for="dict in dict.type.$column.dictType"
+                  :key="dict.value"
+                  :label="dict.label"
+                  :value="dict.value"
+                ></el-option>
+              </el-select>
+            </template>
+          </el-table-column>
+#elseif($column.list && ($column.htmlType == "select" || $column.htmlType == "radio") && "" == $column.dictType)
+          <el-table-column label="$comment" prop="${javaField}" width="150">
+            <template slot-scope="scope">
+              <el-select v-model="scope.row.$javaField" placeholder="璇烽�夋嫨$comment">
+                <el-option label="璇烽�夋嫨瀛楀吀鐢熸垚" value="" />
+              </el-select>
+            </template>
+          </el-table-column>
+#end
+#end
+        </el-table>
+#end
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}";
+
+export default {
+  name: "${BusinessName}",
+#if(${dicts} != '')
+  dicts: [${dicts}],
+#end
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      titleName: "",
+      // 閫変腑鏁扮粍
+      ids: [],
+#if($table.sub)
+      // 瀛愯〃閫変腑鏁版嵁
+      checked${subClassName}: [],
+#end
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // ${functionName}琛ㄦ牸鏁版嵁
+      ${businessName}List: [],
+#if($table.sub)
+      // ${subTable.functionName}琛ㄦ牸鏁版嵁
+      ${subclassName}List: [],
+#end
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+      // $comment鏃堕棿鑼冨洿
+      daterange${AttrName}: [],
+#end
+#end
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+#foreach ($column in $columns)
+#if($column.query)
+        $column.javaField: null#if($foreach.count != $columns.size()),#end
+#end
+#end
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+#foreach ($column in $columns)
+#if($column.required)
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+        $column.javaField: [
+          { required: true, message: "$comment涓嶈兘涓虹┖", trigger: #if($column.htmlType == "select" || $column.htmlType == "radio")"change"#else"blur"#end }
+        ]#if($foreach.count != $columns.size()),#end
+#end
+#end
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 鏌ヨ${functionName}鍒楄〃 */
+    getList() {
+      this.loading = true;
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+      this.queryParams.params = {};
+#break
+#end
+#end
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+      if (null != this.daterange${AttrName} && '' != this.daterange${AttrName}) {
+        this.queryParams.params["begin${AttrName}"] = this.daterange${AttrName}[0];
+        this.queryParams.params["end${AttrName}"] = this.daterange${AttrName}[1];
+      }
+#end
+#end
+      list${BusinessName}(this.queryParams).then(response => {
+        this.${businessName}List = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+#foreach ($column in $columns)
+#if($column.htmlType == "checkbox")
+        $column.javaField: []#if($foreach.count != $columns.size()),#end
+#else
+        $column.javaField: null#if($foreach.count != $columns.size()),#end
+#end
+#end
+      };
+#if($table.sub)
+      this.${subclassName}List = [];
+#end
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+      this.daterange${AttrName} = [];
+#end
+#end
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.${pkColumn.javaField})
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.titleName = "娣诲姞${functionName}";
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.reset();
+      const ${pkColumn.javaField} = row.${pkColumn.javaField} || this.ids
+      get${BusinessName}(${pkColumn.javaField}).then(response => {
+        this.form = response.data;
+#foreach ($column in $columns)
+#if($column.htmlType == "checkbox")
+        this.form.$column.javaField = this.form.${column.javaField}.split(",");
+#end
+#end
+#if($table.sub)
+        this.${subclassName}List = response.data.${subclassName}List;
+#end
+        this.open = true;
+        this.titleName = "淇敼${functionName}";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm() {
+      this.#[[$]]#refs["form"].validate(valid => {
+        if (valid) {
+#foreach ($column in $columns)
+#if($column.htmlType == "checkbox")
+          this.form.$column.javaField = this.form.${column.javaField}.join(",");
+#end
+#end
+#if($table.sub)
+          this.form.${subclassName}List = this.${subclassName}List;
+#end
+          if (this.form.${pkColumn.javaField} != null) {
+            update${BusinessName}(this.form).then(response => {
+              this.#[[$modal]]#.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            add${BusinessName}(this.form).then(response => {
+              this.#[[$modal]]#.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const ${pkColumn.javaField}s = row.${pkColumn.javaField} || this.ids;
+      this.#[[$modal]]#.confirm('鏄惁纭鍒犻櫎${functionName}缂栧彿涓�"' + ${pkColumn.javaField}s + '"鐨勬暟鎹」锛�').then(function() {
+        return del${BusinessName}(${pkColumn.javaField}s);
+      }).then(() => {
+        this.getList();
+        this.#[[$modal]]#.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    },
+#if($table.sub)
+	/** ${subTable.functionName}搴忓彿 */
+    row${subClassName}Index({ row, rowIndex }) {
+      row.index = rowIndex + 1;
+    },
+    /** ${subTable.functionName}娣诲姞鎸夐挳鎿嶄綔 */
+    handleAdd${subClassName}() {
+      let obj = {};
+#foreach($column in $subTable.columns)
+#if($column.pk || $column.javaField == ${subTableFkclassName})
+#elseif($column.list && "" != $javaField)
+      obj.$column.javaField = "";
+#end
+#end
+      this.${subclassName}List.push(obj);
+    },
+    /** ${subTable.functionName}鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete${subClassName}() {
+      if (this.checked${subClassName}.length == 0) {
+        this.#[[$modal]]#.msgError("璇峰厛閫夋嫨瑕佸垹闄ょ殑${subTable.functionName}鏁版嵁");
+      } else {
+        const ${subclassName}List = this.${subclassName}List;
+        const checked${subClassName} = this.checked${subClassName};
+        this.${subclassName}List = ${subclassName}List.filter(function(item) {
+          return checked${subClassName}.indexOf(item.index) == -1
+        });
+      }
+    },
+    /** 澶嶉�夋閫変腑鏁版嵁 */
+    handle${subClassName}SelectionChange(selection) {
+      this.checked${subClassName} = selection.map(item => item.index)
+    },
+#end
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('${moduleName}/${businessName}/export', {
+        ...this.queryParams
+      }, `${businessName}_#[[${new Date().getTime()}]]#.xlsx`)
+    }
+  }
+};
+</script>
diff --git a/jcdm-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm b/jcdm-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm
new file mode 100644
index 0000000..c54d62b
--- /dev/null
+++ b/jcdm-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm
@@ -0,0 +1,474 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
+#foreach($column in $columns)
+#if($column.query)
+#set($dictType=$column.dictType)
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($column.htmlType == "input")
+      <el-form-item label="${comment}" prop="${column.javaField}">
+        <el-input
+          v-model="queryParams.${column.javaField}"
+          placeholder="璇疯緭鍏�${comment}"
+          clearable
+          @keyup.enter="handleQuery"
+        />
+      </el-form-item>
+#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && "" != $dictType)
+      <el-form-item label="${comment}" prop="${column.javaField}">
+        <el-select v-model="queryParams.${column.javaField}" placeholder="璇烽�夋嫨${comment}" clearable>
+          <el-option
+            v-for="dict in ${dictType}"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && $dictType)
+      <el-form-item label="${comment}" prop="${column.javaField}">
+        <el-select v-model="queryParams.${column.javaField}" placeholder="璇烽�夋嫨${comment}" clearable>
+          <el-option label="璇烽�夋嫨瀛楀吀鐢熸垚" value="" />
+        </el-select>
+      </el-form-item>
+#elseif($column.htmlType == "datetime" && $column.queryType != "BETWEEN")
+      <el-form-item label="${comment}" prop="${column.javaField}">
+        <el-date-picker clearable
+          v-model="queryParams.${column.javaField}"
+          type="date"
+          value-format="YYYY-MM-DD"
+          placeholder="閫夋嫨${comment}">
+        </el-date-picker>
+      </el-form-item>
+#elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+      <el-form-item label="${comment}" style="width: 308px">
+        <el-date-picker
+          v-model="daterange${AttrName}"
+          value-format="YYYY-MM-DD"
+          type="daterange"
+          range-separator="-"
+          start-placeholder="寮�濮嬫棩鏈�"
+          end-placeholder="缁撴潫鏃ユ湡"
+        ></el-date-picker>
+      </el-form-item>
+#end
+#end
+#end
+      <el-form-item>
+        <el-button type="primary" icon="Search" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="Refresh" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="Plus"
+          @click="handleAdd"
+          v-hasPermi="['${moduleName}:${businessName}:add']"
+        >鏂板</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="info"
+          plain
+          icon="Sort"
+          @click="toggleExpandAll"
+        >灞曞紑/鎶樺彔</el-button>
+      </el-col>
+      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table
+      v-if="refreshTable"
+      v-loading="loading"
+      :data="${businessName}List"
+      row-key="${treeCode}"
+      :default-expand-all="isExpandAll"
+      :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
+    >
+#foreach($column in $columns)
+#set($javaField=$column.javaField)
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($column.pk)
+#elseif($column.list && $column.htmlType == "datetime")
+      <el-table-column label="${comment}" align="center" prop="${javaField}" width="180">
+        <template #default="scope">
+          <span>{{ parseTime(scope.row.${javaField}, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+#elseif($column.list && $column.htmlType == "imageUpload")
+      <el-table-column label="${comment}" align="center" prop="${javaField}" width="100">
+        <template #default="scope">
+          <image-preview :src="scope.row.${javaField}" :width="50" :height="50"/>
+        </template>
+      </el-table-column>
+#elseif($column.list && "" != $column.dictType)
+      <el-table-column label="${comment}" align="center" prop="${javaField}">
+        <template #default="scope">
+#if($column.htmlType == "checkbox")
+          <dict-tag :options="${column.dictType}" :value="scope.row.${javaField} ? scope.row.${javaField}.split(',') : []"/>
+#else
+          <dict-tag :options="${column.dictType}" :value="scope.row.${javaField}"/>
+#end
+        </template>
+      </el-table-column>
+#elseif($column.list && "" != $javaField)
+#if(${foreach.index} == 1)
+      <el-table-column label="${comment}" prop="${javaField}" />
+#else
+      <el-table-column label="${comment}" align="center" prop="${javaField}" />
+#end
+#end
+#end
+      <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+        <template #default="scope">
+          <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['${moduleName}:${businessName}:edit']">淇敼</el-button>
+          <el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)" v-hasPermi="['${moduleName}:${businessName}:add']">鏂板</el-button>
+          <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['${moduleName}:${businessName}:remove']">鍒犻櫎</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- 娣诲姞鎴栦慨鏀�${functionName}瀵硅瘽妗� -->
+    <el-dialog :title="title" v-model="open" width="500px" append-to-body>
+      <el-form ref="${businessName}Ref" :model="form" :rules="rules" label-width="80px">
+#foreach($column in $columns)
+#set($field=$column.javaField)
+#if($column.insert && !$column.pk)
+#if(($column.usableColumn) || (!$column.superColumn))
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#set($dictType=$column.dictType)
+#if("" != $treeParentCode && $column.javaField == $treeParentCode)
+        <el-form-item label="${comment}" prop="${treeParentCode}">
+          <el-tree-select
+            v-model="form.${treeParentCode}"
+            :data="${businessName}Options"
+            :props="{ value: '${treeCode}', label: '${treeName}', children: 'children' }"
+            value-key="${treeCode}"
+            placeholder="璇烽�夋嫨${comment}"
+            check-strictly
+          />
+        </el-form-item>
+#elseif($column.htmlType == "input")
+        <el-form-item label="${comment}" prop="${field}">
+          <el-input v-model="form.${field}" placeholder="璇疯緭鍏�${comment}" />
+        </el-form-item>
+#elseif($column.htmlType == "imageUpload")
+        <el-form-item label="${comment}" prop="${field}">
+          <image-upload v-model="form.${field}"/>
+        </el-form-item>
+#elseif($column.htmlType == "fileUpload")
+        <el-form-item label="${comment}" prop="${field}">
+          <file-upload v-model="form.${field}"/>
+        </el-form-item>
+#elseif($column.htmlType == "editor")
+        <el-form-item label="${comment}">
+          <editor v-model="form.${field}" :min-height="192"/>
+        </el-form-item>
+#elseif($column.htmlType == "select" && "" != $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-select v-model="form.${field}" placeholder="璇烽�夋嫨${comment}">
+            <el-option
+              v-for="dict in ${dictType}"
+              :key="dict.value"
+              :label="dict.label"
+#if($column.javaType == "Integer" || $column.javaType == "Long")
+              :value="parseInt(dict.value)"
+#else
+              :value="dict.value"
+#end
+            ></el-option>
+          </el-select>
+        </el-form-item>
+#elseif($column.htmlType == "select" && $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-select v-model="form.${field}" placeholder="璇烽�夋嫨${comment}">
+            <el-option label="璇烽�夋嫨瀛楀吀鐢熸垚" value="" />
+          </el-select>
+        </el-form-item>
+#elseif($column.htmlType == "checkbox" && "" != $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-checkbox-group v-model="form.${field}">
+            <el-checkbox
+              v-for="dict in ${dictType}"
+              :key="dict.value"
+              :label="dict.value">
+              {{dict.label}}
+            </el-checkbox>
+          </el-checkbox-group>
+        </el-form-item>
+#elseif($column.htmlType == "checkbox" && $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-checkbox-group v-model="form.${field}">
+            <el-checkbox>璇烽�夋嫨瀛楀吀鐢熸垚</el-checkbox>
+          </el-checkbox-group>
+        </el-form-item>
+#elseif($column.htmlType == "radio" && "" != $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-radio-group v-model="form.${field}">
+            <el-radio
+              v-for="dict in ${dictType}"
+              :key="dict.value"
+#if($column.javaType == "Integer" || $column.javaType == "Long")
+              :label="parseInt(dict.value)"
+#else
+              :label="dict.value"
+#end
+            >{{dict.label}}</el-radio>
+          </el-radio-group>
+        </el-form-item>
+#elseif($column.htmlType == "radio" && $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-radio-group v-model="form.${field}">
+            <el-radio label="1">璇烽�夋嫨瀛楀吀鐢熸垚</el-radio>
+          </el-radio-group>
+        </el-form-item>
+#elseif($column.htmlType == "datetime")
+        <el-form-item label="${comment}" prop="${field}">
+          <el-date-picker clearable
+            v-model="form.${field}"
+            type="date"
+            value-format="YYYY-MM-DD"
+            placeholder="閫夋嫨${comment}">
+          </el-date-picker>
+        </el-form-item>
+#elseif($column.htmlType == "textarea")
+        <el-form-item label="${comment}" prop="${field}">
+          <el-input v-model="form.${field}" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
+        </el-form-item>
+#end
+#end
+#end
+#end
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+          <el-button @click="cancel">鍙� 娑�</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup name="${BusinessName}">
+import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}";
+
+const { proxy } = getCurrentInstance();
+#if(${dicts} != '')
+#set($dictsNoSymbol=$dicts.replace("'", ""))
+const { ${dictsNoSymbol} } = proxy.useDict(${dicts});
+#end
+
+const ${businessName}List = ref([]);
+const ${businessName}Options = ref([]);
+const open = ref(false);
+const loading = ref(true);
+const showSearch = ref(true);
+const title = ref("");
+const isExpandAll = ref(true);
+const refreshTable = ref(true);
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+const daterange${AttrName} = ref([]);
+#end
+#end
+
+const data = reactive({
+  form: {},
+  queryParams: {
+    #foreach ($column in $columns)
+#if($column.query)
+    $column.javaField: null#if($foreach.count != $columns.size()),#end
+#end
+#end
+  },
+  rules: {
+    #foreach ($column in $columns)
+#if($column.required)
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+    $column.javaField: [
+      { required: true, message: "$comment涓嶈兘涓虹┖", trigger: #if($column.htmlType == "select" || $column.htmlType == "radio")"change"#else"blur"#end }
+    ]#if($foreach.count != $columns.size()),#end
+#end
+#end
+  }
+});
+
+const { queryParams, form, rules } = toRefs(data);
+
+/** 鏌ヨ${functionName}鍒楄〃 */
+function getList() {
+  loading.value = true;
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+  queryParams.value.params = {};
+#break
+#end
+#end
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+  if (null != daterange${AttrName} && '' != daterange${AttrName}) {
+    queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0];
+    queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1];
+  }
+#end
+#end
+  list${BusinessName}(queryParams.value).then(response => {
+    ${businessName}List.value = proxy.handleTree(response.data, "${treeCode}", "${treeParentCode}");
+    loading.value = false;
+  });
+}
+
+/** 鏌ヨ${functionName}涓嬫媺鏍戠粨鏋� */
+function getTreeselect() {
+  list${BusinessName}().then(response => {
+    ${businessName}Options.value = [];
+    const data = { ${treeCode}: 0, ${treeName}: '椤剁骇鑺傜偣', children: [] };
+    data.children = proxy.handleTree(response.data, "${treeCode}", "${treeParentCode}");
+    ${businessName}Options.value.push(data);
+  });
+}
+	
+// 鍙栨秷鎸夐挳
+function cancel() {
+  open.value = false;
+  reset();
+}
+
+// 琛ㄥ崟閲嶇疆
+function reset() {
+  form.value = {
+#foreach ($column in $columns)
+#if($column.htmlType == "checkbox")
+    $column.javaField: []#if($foreach.count != $columns.size()),#end
+#else
+    $column.javaField: null#if($foreach.count != $columns.size()),#end
+#end
+#end
+  };
+  proxy.resetForm("${businessName}Ref");
+}
+
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+function handleQuery() {
+  getList();
+}
+
+/** 閲嶇疆鎸夐挳鎿嶄綔 */
+function resetQuery() {
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+  daterange${AttrName}.value = [];
+#end
+#end
+  proxy.resetForm("queryRef");
+  handleQuery();
+}
+
+/** 鏂板鎸夐挳鎿嶄綔 */
+function handleAdd(row) {
+  reset();
+  getTreeselect();
+  if (row != null && row.${treeCode}) {
+    form.value.${treeParentCode} = row.${treeCode};
+  } else {
+    form.value.${treeParentCode} = 0;
+  }
+  open.value = true;
+  title.value = "娣诲姞${functionName}";
+}
+
+/** 灞曞紑/鎶樺彔鎿嶄綔 */
+function toggleExpandAll() {
+  refreshTable.value = false;
+  isExpandAll.value = !isExpandAll.value;
+  nextTick(() => {
+    refreshTable.value = true;
+  });
+}
+
+/** 淇敼鎸夐挳鎿嶄綔 */
+async function handleUpdate(row) {
+  reset();
+  await getTreeselect();
+  if (row != null) {
+    form.value.${treeParentCode} = row.${treeParentCode};
+  }
+  get${BusinessName}(row.${pkColumn.javaField}).then(response => {
+    form.value = response.data;
+#foreach ($column in $columns)
+#if($column.htmlType == "checkbox")
+    form.value.$column.javaField = form.value.${column.javaField}.split(",");
+#end
+#end
+    open.value = true;
+    title.value = "淇敼${functionName}";
+  });
+}
+
+/** 鎻愪氦鎸夐挳 */
+function submitForm() {
+  proxy.#[[$]]#refs["${businessName}Ref"].validate(valid => {
+    if (valid) {
+#foreach ($column in $columns)
+#if($column.htmlType == "checkbox")
+      form.value.$column.javaField = form.value.${column.javaField}.join(",");
+#end
+#end
+      if (form.value.${pkColumn.javaField} != null) {
+        update${BusinessName}(form.value).then(response => {
+          proxy.#[[$modal]]#.msgSuccess("淇敼鎴愬姛");
+          open.value = false;
+          getList();
+        });
+      } else {
+        add${BusinessName}(form.value).then(response => {
+          proxy.#[[$modal]]#.msgSuccess("鏂板鎴愬姛");
+          open.value = false;
+          getList();
+        });
+      }
+    }
+  });
+}
+
+/** 鍒犻櫎鎸夐挳鎿嶄綔 */
+function handleDelete(row) {
+  proxy.#[[$modal]]#.confirm('鏄惁纭鍒犻櫎${functionName}缂栧彿涓�"' + row.${pkColumn.javaField} + '"鐨勬暟鎹」锛�').then(function() {
+    return del${BusinessName}(row.${pkColumn.javaField});
+  }).then(() => {
+    getList();
+    proxy.#[[$modal]]#.msgSuccess("鍒犻櫎鎴愬姛");
+  }).catch(() => {});
+}
+
+getList();
+</script>
diff --git a/jcdm-generator/src/main/resources/vm/vue/v3/index.vue.vm b/jcdm-generator/src/main/resources/vm/vue/v3/index.vue.vm
new file mode 100644
index 0000000..8b25665
--- /dev/null
+++ b/jcdm-generator/src/main/resources/vm/vue/v3/index.vue.vm
@@ -0,0 +1,590 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
+#foreach($column in $columns)
+#if($column.query)
+#set($dictType=$column.dictType)
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($column.htmlType == "input")
+      <el-form-item label="${comment}" prop="${column.javaField}">
+        <el-input
+          v-model="queryParams.${column.javaField}"
+          placeholder="璇疯緭鍏�${comment}"
+          clearable
+          @keyup.enter="handleQuery"
+        />
+      </el-form-item>
+#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && "" != $dictType)
+      <el-form-item label="${comment}" prop="${column.javaField}">
+        <el-select v-model="queryParams.${column.javaField}" placeholder="璇烽�夋嫨${comment}" clearable>
+          <el-option
+            v-for="dict in ${dictType}"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && $dictType)
+      <el-form-item label="${comment}" prop="${column.javaField}">
+        <el-select v-model="queryParams.${column.javaField}" placeholder="璇烽�夋嫨${comment}" clearable>
+          <el-option label="璇烽�夋嫨瀛楀吀鐢熸垚" value="" />
+        </el-select>
+      </el-form-item>
+#elseif($column.htmlType == "datetime" && $column.queryType != "BETWEEN")
+      <el-form-item label="${comment}" prop="${column.javaField}">
+        <el-date-picker clearable
+          v-model="queryParams.${column.javaField}"
+          type="date"
+          value-format="YYYY-MM-DD"
+          placeholder="璇烽�夋嫨${comment}">
+        </el-date-picker>
+      </el-form-item>
+#elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+      <el-form-item label="${comment}" style="width: 308px">
+        <el-date-picker
+          v-model="daterange${AttrName}"
+          value-format="YYYY-MM-DD"
+          type="daterange"
+          range-separator="-"
+          start-placeholder="寮�濮嬫棩鏈�"
+          end-placeholder="缁撴潫鏃ユ湡"
+        ></el-date-picker>
+      </el-form-item>
+#end
+#end
+#end
+      <el-form-item>
+        <el-button type="primary" icon="Search" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="Refresh" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="Plus"
+          @click="handleAdd"
+          v-hasPermi="['${moduleName}:${businessName}:add']"
+        >鏂板</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="Edit"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['${moduleName}:${businessName}:edit']"
+        >淇敼</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="Delete"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['${moduleName}:${businessName}:remove']"
+        >鍒犻櫎</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="Download"
+          @click="handleExport"
+          v-hasPermi="['${moduleName}:${businessName}:export']"
+        >瀵煎嚭</el-button>
+      </el-col>
+      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="${businessName}List" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+#foreach($column in $columns)
+#set($javaField=$column.javaField)
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($column.pk)
+      <el-table-column label="${comment}" align="center" prop="${javaField}" />
+#elseif($column.list && $column.htmlType == "datetime")
+      <el-table-column label="${comment}" align="center" prop="${javaField}" width="180">
+        <template #default="scope">
+          <span>{{ parseTime(scope.row.${javaField}, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+#elseif($column.list && $column.htmlType == "imageUpload")
+      <el-table-column label="${comment}" align="center" prop="${javaField}" width="100">
+        <template #default="scope">
+          <image-preview :src="scope.row.${javaField}" :width="50" :height="50"/>
+        </template>
+      </el-table-column>
+#elseif($column.list && "" != $column.dictType)
+      <el-table-column label="${comment}" align="center" prop="${javaField}">
+        <template #default="scope">
+#if($column.htmlType == "checkbox")
+          <dict-tag :options="${column.dictType}" :value="scope.row.${javaField} ? scope.row.${javaField}.split(',') : []"/>
+#else
+          <dict-tag :options="${column.dictType}" :value="scope.row.${javaField}"/>
+#end
+        </template>
+      </el-table-column>
+#elseif($column.list && "" != $javaField)
+      <el-table-column label="${comment}" align="center" prop="${javaField}" />
+#end
+#end
+      <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+        <template #default="scope">
+          <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['${moduleName}:${businessName}:edit']">淇敼</el-button>
+          <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['${moduleName}:${businessName}:remove']">鍒犻櫎</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    
+    <pagination
+      v-show="total>0"
+      :total="total"
+      v-model:page="queryParams.pageNum"
+      v-model:limit="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 娣诲姞鎴栦慨鏀�${functionName}瀵硅瘽妗� -->
+    <el-dialog :title="title" v-model="open" width="500px" append-to-body>
+      <el-form ref="${businessName}Ref" :model="form" :rules="rules" label-width="80px">
+#foreach($column in $columns)
+#set($field=$column.javaField)
+#if($column.insert && !$column.pk)
+#if(($column.usableColumn) || (!$column.superColumn))
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#set($dictType=$column.dictType)
+#if($column.htmlType == "input")
+        <el-form-item label="${comment}" prop="${field}">
+          <el-input v-model="form.${field}" placeholder="璇疯緭鍏�${comment}" />
+        </el-form-item>
+#elseif($column.htmlType == "imageUpload")
+        <el-form-item label="${comment}" prop="${field}">
+          <image-upload v-model="form.${field}"/>
+        </el-form-item>
+#elseif($column.htmlType == "fileUpload")
+        <el-form-item label="${comment}" prop="${field}">
+          <file-upload v-model="form.${field}"/>
+        </el-form-item>
+#elseif($column.htmlType == "editor")
+        <el-form-item label="${comment}">
+          <editor v-model="form.${field}" :min-height="192"/>
+        </el-form-item>
+#elseif($column.htmlType == "select" && "" != $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-select v-model="form.${field}" placeholder="璇烽�夋嫨${comment}">
+            <el-option
+              v-for="dict in ${dictType}"
+              :key="dict.value"
+              :label="dict.label"
+#if($column.javaType == "Integer" || $column.javaType == "Long")
+              :value="parseInt(dict.value)"
+#else
+              :value="dict.value"
+#end
+            ></el-option>
+          </el-select>
+        </el-form-item>
+#elseif($column.htmlType == "select" && $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-select v-model="form.${field}" placeholder="璇烽�夋嫨${comment}">
+            <el-option label="璇烽�夋嫨瀛楀吀鐢熸垚" value="" />
+          </el-select>
+        </el-form-item>
+#elseif($column.htmlType == "checkbox" && "" != $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-checkbox-group v-model="form.${field}">
+            <el-checkbox
+              v-for="dict in ${dictType}"
+              :key="dict.value"
+              :label="dict.value">
+              {{dict.label}}
+            </el-checkbox>
+          </el-checkbox-group>
+        </el-form-item>
+#elseif($column.htmlType == "checkbox" && $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-checkbox-group v-model="form.${field}">
+            <el-checkbox>璇烽�夋嫨瀛楀吀鐢熸垚</el-checkbox>
+          </el-checkbox-group>
+        </el-form-item>
+#elseif($column.htmlType == "radio" && "" != $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-radio-group v-model="form.${field}">
+            <el-radio
+              v-for="dict in ${dictType}"
+              :key="dict.value"
+#if($column.javaType == "Integer" || $column.javaType == "Long")
+              :label="parseInt(dict.value)"
+#else
+              :label="dict.value"
+#end
+            >{{dict.label}}</el-radio>
+          </el-radio-group>
+        </el-form-item>
+#elseif($column.htmlType == "radio" && $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-radio-group v-model="form.${field}">
+            <el-radio label="1">璇烽�夋嫨瀛楀吀鐢熸垚</el-radio>
+          </el-radio-group>
+        </el-form-item>
+#elseif($column.htmlType == "datetime")
+        <el-form-item label="${comment}" prop="${field}">
+          <el-date-picker clearable
+            v-model="form.${field}"
+            type="date"
+            value-format="YYYY-MM-DD"
+            placeholder="璇烽�夋嫨${comment}">
+          </el-date-picker>
+        </el-form-item>
+#elseif($column.htmlType == "textarea")
+        <el-form-item label="${comment}" prop="${field}">
+          <el-input v-model="form.${field}" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
+        </el-form-item>
+#end
+#end
+#end
+#end
+#if($table.sub)
+        <el-divider content-position="center">${subTable.functionName}淇℃伅</el-divider>
+        <el-row :gutter="10" class="mb8">
+          <el-col :span="1.5">
+            <el-button type="primary" icon="Plus" @click="handleAdd${subClassName}">娣诲姞</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button type="danger" icon="Delete" @click="handleDelete${subClassName}">鍒犻櫎</el-button>
+          </el-col>
+        </el-row>
+        <el-table :data="${subclassName}List" :row-class-name="row${subClassName}Index" @selection-change="handle${subClassName}SelectionChange" ref="${subclassName}">
+          <el-table-column type="selection" width="50" align="center" />
+          <el-table-column label="搴忓彿" align="center" prop="index" width="50"/>
+#foreach($column in $subTable.columns)
+#set($javaField=$column.javaField)
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($column.pk || $javaField == ${subTableFkclassName})
+#elseif($column.list && $column.htmlType == "input")
+          <el-table-column label="$comment" prop="${javaField}" width="150">
+            <template #default="scope">
+              <el-input v-model="scope.row.$javaField" placeholder="璇疯緭鍏�$comment" />
+            </template>
+          </el-table-column>
+#elseif($column.list && $column.htmlType == "datetime")
+          <el-table-column label="$comment" prop="${javaField}" width="240">
+            <template #default="scope">
+              <el-date-picker clearable
+                v-model="scope.row.$javaField"
+                type="date"
+                value-format="YYYY-MM-DD"
+                placeholder="璇烽�夋嫨$comment">
+              </el-date-picker>
+            </template>
+          </el-table-column>
+#elseif($column.list && ($column.htmlType == "select" || $column.htmlType == "radio") && "" != $column.dictType)
+          <el-table-column label="$comment" prop="${javaField}" width="150">
+            <template #default="scope">
+              <el-select v-model="scope.row.$javaField" placeholder="璇烽�夋嫨$comment">
+                <el-option
+                  v-for="dict in $column.dictType"
+                  :key="dict.value"
+                  :label="dict.label"
+                  :value="dict.value"
+                ></el-option>
+              </el-select>
+            </template>
+          </el-table-column>
+#elseif($column.list && ($column.htmlType == "select" || $column.htmlType == "radio") && "" == $column.dictType)
+          <el-table-column label="$comment" prop="${javaField}" width="150">
+            <template #default="scope">
+              <el-select v-model="scope.row.$javaField" placeholder="璇烽�夋嫨$comment">
+                <el-option label="璇烽�夋嫨瀛楀吀鐢熸垚" value="" />
+              </el-select>
+            </template>
+          </el-table-column>
+#end
+#end
+        </el-table>
+#end
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+          <el-button @click="cancel">鍙� 娑�</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup name="${BusinessName}">
+import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}";
+
+const { proxy } = getCurrentInstance();
+#if(${dicts} != '')
+#set($dictsNoSymbol=$dicts.replace("'", ""))
+const { ${dictsNoSymbol} } = proxy.useDict(${dicts});
+#end
+
+const ${businessName}List = ref([]);
+#if($table.sub)
+const ${subclassName}List = ref([]);
+#end
+const open = ref(false);
+const loading = ref(true);
+const showSearch = ref(true);
+const ids = ref([]);
+#if($table.sub)
+const checked${subClassName} = ref([]);
+#end
+const single = ref(true);
+const multiple = ref(true);
+const total = ref(0);
+const title = ref("");
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+const daterange${AttrName} = ref([]);
+#end
+#end
+
+const data = reactive({
+  form: {},
+  queryParams: {
+    pageNum: 1,
+    pageSize: 10,
+    #foreach ($column in $columns)
+#if($column.query)
+    $column.javaField: null#if($foreach.count != $columns.size()),#end
+#end
+#end
+  },
+  rules: {
+    #foreach ($column in $columns)
+#if($column.required)
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+    $column.javaField: [
+      { required: true, message: "$comment涓嶈兘涓虹┖", trigger: #if($column.htmlType == "select" || $column.htmlType == "radio")"change"#else"blur"#end }
+    ]#if($foreach.count != $columns.size()),#end
+#end
+#end
+  }
+});
+
+const { queryParams, form, rules } = toRefs(data);
+
+/** 鏌ヨ${functionName}鍒楄〃 */
+function getList() {
+  loading.value = true;
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+  queryParams.value.params = {};
+#break
+#end
+#end
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+  if (null != daterange${AttrName} && '' != daterange${AttrName}) {
+    queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0];
+    queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1];
+  }
+#end
+#end
+  list${BusinessName}(queryParams.value).then(response => {
+    ${businessName}List.value = response.rows;
+    total.value = response.total;
+    loading.value = false;
+  });
+}
+
+// 鍙栨秷鎸夐挳
+function cancel() {
+  open.value = false;
+  reset();
+}
+
+// 琛ㄥ崟閲嶇疆
+function reset() {
+  form.value = {
+#foreach ($column in $columns)
+#if($column.htmlType == "checkbox")
+    $column.javaField: []#if($foreach.count != $columns.size()),#end
+#else
+    $column.javaField: null#if($foreach.count != $columns.size()),#end
+#end
+#end
+  };
+#if($table.sub)
+  ${subclassName}List.value = [];
+#end
+  proxy.resetForm("${businessName}Ref");
+}
+
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+function handleQuery() {
+  queryParams.value.pageNum = 1;
+  getList();
+}
+
+/** 閲嶇疆鎸夐挳鎿嶄綔 */
+function resetQuery() {
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+  daterange${AttrName}.value = [];
+#end
+#end
+  proxy.resetForm("queryRef");
+  handleQuery();
+}
+
+// 澶氶�夋閫変腑鏁版嵁
+function handleSelectionChange(selection) {
+  ids.value = selection.map(item => item.${pkColumn.javaField});
+  single.value = selection.length != 1;
+  multiple.value = !selection.length;
+}
+
+/** 鏂板鎸夐挳鎿嶄綔 */
+function handleAdd() {
+  reset();
+  open.value = true;
+  title.value = "娣诲姞${functionName}";
+}
+
+/** 淇敼鎸夐挳鎿嶄綔 */
+function handleUpdate(row) {
+  reset();
+  const _${pkColumn.javaField} = row.${pkColumn.javaField} || ids.value
+  get${BusinessName}(_${pkColumn.javaField}).then(response => {
+    form.value = response.data;
+#foreach ($column in $columns)
+#if($column.htmlType == "checkbox")
+    form.value.$column.javaField = form.value.${column.javaField}.split(",");
+#end
+#end
+#if($table.sub)
+    ${subclassName}List.value = response.data.${subclassName}List;
+#end
+    open.value = true;
+    title.value = "淇敼${functionName}";
+  });
+}
+
+/** 鎻愪氦鎸夐挳 */
+function submitForm() {
+  proxy.#[[$]]#refs["${businessName}Ref"].validate(valid => {
+    if (valid) {
+#foreach ($column in $columns)
+#if($column.htmlType == "checkbox")
+      form.value.$column.javaField = form.value.${column.javaField}.join(",");
+#end
+#end
+#if($table.sub)
+      form.value.${subclassName}List = ${subclassName}List.value;
+#end
+      if (form.value.${pkColumn.javaField} != null) {
+        update${BusinessName}(form.value).then(response => {
+          proxy.#[[$modal]]#.msgSuccess("淇敼鎴愬姛");
+          open.value = false;
+          getList();
+        });
+      } else {
+        add${BusinessName}(form.value).then(response => {
+          proxy.#[[$modal]]#.msgSuccess("鏂板鎴愬姛");
+          open.value = false;
+          getList();
+        });
+      }
+    }
+  });
+}
+
+/** 鍒犻櫎鎸夐挳鎿嶄綔 */
+function handleDelete(row) {
+  const _${pkColumn.javaField}s = row.${pkColumn.javaField} || ids.value;
+  proxy.#[[$modal]]#.confirm('鏄惁纭鍒犻櫎${functionName}缂栧彿涓�"' + _${pkColumn.javaField}s + '"鐨勬暟鎹」锛�').then(function() {
+    return del${BusinessName}(_${pkColumn.javaField}s);
+  }).then(() => {
+    getList();
+    proxy.#[[$modal]]#.msgSuccess("鍒犻櫎鎴愬姛");
+  }).catch(() => {});
+}
+
+#if($table.sub)
+/** ${subTable.functionName}搴忓彿 */
+function row${subClassName}Index({ row, rowIndex }) {
+  row.index = rowIndex + 1;
+}
+
+/** ${subTable.functionName}娣诲姞鎸夐挳鎿嶄綔 */
+function handleAdd${subClassName}() {
+  let obj = {};
+#foreach($column in $subTable.columns)
+#if($column.pk || $column.javaField == ${subTableFkclassName})
+#elseif($column.list && "" != $javaField)
+  obj.$column.javaField = "";
+#end
+#end
+  ${subclassName}List.value.push(obj);
+}
+
+/** ${subTable.functionName}鍒犻櫎鎸夐挳鎿嶄綔 */
+function handleDelete${subClassName}() {
+  if (checked${subClassName}.value.length == 0) {
+    proxy.#[[$modal]]#.msgError("璇峰厛閫夋嫨瑕佸垹闄ょ殑${subTable.functionName}鏁版嵁");
+  } else {
+    const ${subclassName}s = ${subclassName}List.value;
+    const checked${subClassName}s = checked${subClassName}.value;
+    ${subclassName}List.value = ${subclassName}s.filter(function(item) {
+      return checked${subClassName}s.indexOf(item.index) == -1
+    });
+  }
+}
+
+/** 澶嶉�夋閫変腑鏁版嵁 */
+function handle${subClassName}SelectionChange(selection) {
+  checked${subClassName}.value = selection.map(item => item.index)
+}
+
+#end
+/** 瀵煎嚭鎸夐挳鎿嶄綔 */
+function handleExport() {
+  proxy.download('${moduleName}/${businessName}/export', {
+    ...queryParams.value
+  }, `${businessName}_#[[${new Date().getTime()}]]#.xlsx`)
+}
+
+getList();
+</script>
diff --git a/jcdm-generator/src/main/resources/vm/xml/mapper.xml.vm b/jcdm-generator/src/main/resources/vm/xml/mapper.xml.vm
new file mode 100644
index 0000000..0ceb3d8
--- /dev/null
+++ b/jcdm-generator/src/main/resources/vm/xml/mapper.xml.vm
@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="${packageName}.mapper.${ClassName}Mapper">
+    
+    <resultMap type="${ClassName}" id="${ClassName}Result">
+#foreach ($column in $columns)
+        <result property="${column.javaField}"    column="${column.columnName}"    />
+#end
+    </resultMap>
+#if($table.sub)
+
+    <resultMap id="${ClassName}${subClassName}Result" type="${ClassName}" extends="${ClassName}Result">
+        <collection property="${subclassName}List" notNullColumn="sub_${subTable.pkColumn.columnName}" javaType="java.util.List" resultMap="${subClassName}Result" />
+    </resultMap>
+
+    <resultMap type="${subClassName}" id="${subClassName}Result">
+#foreach ($column in $subTable.columns)
+        <result property="${column.javaField}"    column="sub_${column.columnName}"    />
+#end
+    </resultMap>
+#end
+
+    <sql id="select${ClassName}Vo">
+        select#foreach($column in $columns) $column.columnName#if($foreach.count != $columns.size()),#end#end from ${tableName}
+    </sql>
+
+    <select id="select${ClassName}List" parameterType="${ClassName}" resultMap="${ClassName}Result">
+        <include refid="select${ClassName}Vo"/>
+        <where>  
+#foreach($column in $columns)
+#set($queryType=$column.queryType)
+#set($javaField=$column.javaField)
+#set($javaType=$column.javaType)
+#set($columnName=$column.columnName)
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+#if($column.query)
+#if($column.queryType == "EQ")
+            <if test="$javaField != null #if($javaType == 'String' ) and $javaField.trim() != ''#end"> and $columnName = #{$javaField}</if>
+#elseif($queryType == "NE")
+            <if test="$javaField != null #if($javaType == 'String' ) and $javaField.trim() != ''#end"> and $columnName != #{$javaField}</if>
+#elseif($queryType == "GT")
+            <if test="$javaField != null #if($javaType == 'String' ) and $javaField.trim() != ''#end"> and $columnName &gt; #{$javaField}</if>
+#elseif($queryType == "GTE")
+            <if test="$javaField != null #if($javaType == 'String' ) and $javaField.trim() != ''#end"> and $columnName &gt;= #{$javaField}</if>
+#elseif($queryType == "LT")
+            <if test="$javaField != null #if($javaType == 'String' ) and $javaField.trim() != ''#end"> and $columnName &lt; #{$javaField}</if>
+#elseif($queryType == "LTE")
+            <if test="$javaField != null #if($javaType == 'String' ) and $javaField.trim() != ''#end"> and $columnName &lt;= #{$javaField}</if>
+#elseif($queryType == "LIKE")
+            <if test="$javaField != null #if($javaType == 'String' ) and $javaField.trim() != ''#end"> and $columnName like concat('%', #{$javaField}, '%')</if>
+#elseif($queryType == "BETWEEN")
+            <if test="params.begin$AttrName != null and params.begin$AttrName != '' and params.end$AttrName != null and params.end$AttrName != ''"> and $columnName between #{params.begin$AttrName} and #{params.end$AttrName}</if>
+#end
+#end
+#end
+        </where>
+    </select>
+    
+    <select id="select${ClassName}By${pkColumn.capJavaField}" parameterType="${pkColumn.javaType}" resultMap="#if($table.sub)${ClassName}${subClassName}Result#else${ClassName}Result#end">
+#if($table.crud || $table.tree)
+        <include refid="select${ClassName}Vo"/>
+        where ${pkColumn.columnName} = #{${pkColumn.javaField}}
+#elseif($table.sub)
+        select#foreach($column in $columns) a.$column.columnName#if($foreach.count != $columns.size()),#end#end,
+           #foreach($column in $subTable.columns) b.$column.columnName as sub_$column.columnName#if($foreach.count != $subTable.columns.size()),#end#end
+
+        from ${tableName} a
+        left join ${subTableName} b on b.${subTableFkName} = a.${pkColumn.columnName}
+        where a.${pkColumn.columnName} = #{${pkColumn.javaField}}
+#end
+    </select>
+        
+    <insert id="insert${ClassName}" parameterType="${ClassName}"#if($pkColumn.increment) useGeneratedKeys="true" keyProperty="$pkColumn.javaField"#end>
+        insert into ${tableName}
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+#foreach($column in $columns)
+#if($column.columnName != $pkColumn.columnName || !$pkColumn.increment)
+            <if test="$column.javaField != null#if($column.javaType == 'String' && $column.required) and $column.javaField != ''#end">$column.columnName,</if>
+#end
+#end
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+#foreach($column in $columns)
+#if($column.columnName != $pkColumn.columnName || !$pkColumn.increment)
+            <if test="$column.javaField != null#if($column.javaType == 'String' && $column.required) and $column.javaField != ''#end">#{$column.javaField},</if>
+#end
+#end
+         </trim>
+    </insert>
+
+    <update id="update${ClassName}" parameterType="${ClassName}">
+        update ${tableName}
+        <trim prefix="SET" suffixOverrides=",">
+#foreach($column in $columns)
+#if($column.columnName != $pkColumn.columnName)
+            <if test="$column.javaField != null#if($column.javaType == 'String' && $column.required) and $column.javaField != ''#end">$column.columnName = #{$column.javaField},</if>
+#end
+#end
+        </trim>
+        where ${pkColumn.columnName} = #{${pkColumn.javaField}}
+    </update>
+
+    <delete id="delete${ClassName}By${pkColumn.capJavaField}" parameterType="${pkColumn.javaType}">
+        delete from ${tableName} where ${pkColumn.columnName} = #{${pkColumn.javaField}}
+    </delete>
+
+    <delete id="delete${ClassName}By${pkColumn.capJavaField}s" parameterType="String">
+        delete from ${tableName} where ${pkColumn.columnName} in 
+        <foreach item="${pkColumn.javaField}" collection="array" open="(" separator="," close=")">
+            #{${pkColumn.javaField}}
+        </foreach>
+    </delete>
+#if($table.sub)
+    
+    <delete id="delete${subClassName}By${subTableFkClassName}s" parameterType="String">
+        delete from ${subTableName} where ${subTableFkName} in 
+        <foreach item="${subTableFkclassName}" collection="array" open="(" separator="," close=")">
+            #{${subTableFkclassName}}
+        </foreach>
+    </delete>
+
+    <delete id="delete${subClassName}By${subTableFkClassName}" parameterType="${pkColumn.javaType}">
+        delete from ${subTableName} where ${subTableFkName} = #{${subTableFkclassName}}
+    </delete>
+
+    <insert id="batch${subClassName}">
+        insert into ${subTableName}(#foreach($column in $subTable.columns) $column.columnName#if($foreach.count != $subTable.columns.size()),#end#end) values
+		<foreach item="item" index="index" collection="list" separator=",">
+            (#foreach($column in $subTable.columns) #{item.$column.javaField}#if($foreach.count != $subTable.columns.size()),#end#end)
+        </foreach>
+    </insert>
+#end
+</mapper>
\ No newline at end of file
diff --git a/jcdm-main/pom.xml b/jcdm-main/pom.xml
new file mode 100644
index 0000000..4518cee
--- /dev/null
+++ b/jcdm-main/pom.xml
@@ -0,0 +1,101 @@
+<?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.jcdm</groupId>
+        <artifactId>jcdm</artifactId>
+        <version>3.8.6</version>
+    </parent>
+
+    <artifactId>jcdm-main</artifactId>
+
+    <properties>
+        <maven.compiler.source>17</maven.compiler.source>
+        <maven.compiler.target>17</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.jcdm</groupId>
+            <artifactId>jcdm-common</artifactId>
+            <exclusions>
+                <exclusion>
+                    <artifactId>mybatis-spring</artifactId>
+                    <groupId>org.mybatis</groupId>
+                </exclusion>
+                <exclusion>
+                    <artifactId>mybatis</artifactId>
+                    <groupId>org.mybatis</groupId>
+                </exclusion>
+                <exclusion>
+                    <artifactId>jsqlparser</artifactId>
+                    <groupId>com.github.jsqlparser</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>commons-httpclient</groupId>
+            <artifactId>commons-httpclient</artifactId>
+            <version>3.1</version>
+        </dependency>
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+            <version>5.7.4</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+            <version>2.10.1</version>
+        </dependency>
+
+        <!--Server SDK渚濊禆-->
+        <dependency>
+            <groupId>org.eclipse.milo</groupId>
+            <artifactId>sdk-server</artifactId>
+            <version>0.3.6</version>
+        </dependency>
+
+        <!--Client SDK渚濊禆-->
+        <dependency>
+            <groupId>org.eclipse.milo</groupId>
+            <artifactId>sdk-client</artifactId>
+            <version>0.3.6</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.eclipse.milo</groupId>
+            <artifactId>stack-client</artifactId>
+            <version>0.3.6</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.eclipse.milo</groupId>
+            <artifactId>stack-client</artifactId>
+            <version>0.3.6</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.eclipse.milo</groupId>
+            <artifactId>stack-server</artifactId>
+            <version>0.3.6</version>
+        </dependency>
+
+        <!-- 绯荤粺妯″潡-->
+        <dependency>
+            <groupId>com.jcdm</groupId>
+            <artifactId>jcdm-framework</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/beatSetting/controller/BsBeatSettingController.java b/jcdm-main/src/main/java/com/jcdm/main/bs/beatSetting/controller/BsBeatSettingController.java
new file mode 100644
index 0000000..1615c3d
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/beatSetting/controller/BsBeatSettingController.java
@@ -0,0 +1,104 @@
+package com.jcdm.main.bs.beatSetting.controller;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.main.bs.beatSetting.domain.BsBeatSetting;
+import com.jcdm.main.bs.beatSetting.service.IBsBeatSettingService;
+import com.jcdm.common.utils.poi.ExcelUtil;
+import com.jcdm.common.core.page.TableDataInfo;
+
+/**
+ * 鑺傛媿璁剧疆Controller
+ * 
+ * @author Yi
+ * @date 2024-01-05
+ */
+@RestController
+@RequestMapping("/bs/beatSetting")
+public class BsBeatSettingController extends BaseController
+{
+    @Autowired
+    private IBsBeatSettingService bsBeatSettingService;
+
+    /**
+     * 鏌ヨ鑺傛媿璁剧疆鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('bs:beatSetting:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(BsBeatSetting bsBeatSetting)
+    {
+        startPage();
+        List<BsBeatSetting> list = bsBeatSettingService.selectBsBeatSettingList(bsBeatSetting);
+        return getDataTable(list);
+    }
+
+    /**
+     * 瀵煎嚭鑺傛媿璁剧疆鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('bs:beatSetting:export')")
+    @Log(title = "鑺傛媿璁剧疆", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, BsBeatSetting bsBeatSetting)
+    {
+        List<BsBeatSetting> list = bsBeatSettingService.selectBsBeatSettingList(bsBeatSetting);
+        ExcelUtil<BsBeatSetting> util = new ExcelUtil<BsBeatSetting>(BsBeatSetting.class);
+        util.exportExcel(response, list, "鑺傛媿璁剧疆鏁版嵁");
+    }
+
+    /**
+     * 鑾峰彇鑺傛媿璁剧疆璇︾粏淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('bs:beatSetting:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(bsBeatSettingService.selectBsBeatSettingById(id));
+    }
+
+    /**
+     * 鏂板鑺傛媿璁剧疆
+     */
+    @PreAuthorize("@ss.hasPermi('bs:beatSetting:add')")
+    @Log(title = "鑺傛媿璁剧疆", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody BsBeatSetting bsBeatSetting)
+    {
+        return toAjax(bsBeatSettingService.insertBsBeatSetting(bsBeatSetting));
+    }
+
+    /**
+     * 淇敼鑺傛媿璁剧疆
+     */
+    @PreAuthorize("@ss.hasPermi('bs:beatSetting:edit')")
+    @Log(title = "鑺傛媿璁剧疆", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody BsBeatSetting bsBeatSetting)
+    {
+        return toAjax(bsBeatSettingService.updateBsBeatSetting(bsBeatSetting));
+    }
+
+    /**
+     * 鍒犻櫎鑺傛媿璁剧疆
+     */
+    @PreAuthorize("@ss.hasPermi('bs:beatSetting:remove')")
+    @Log(title = "鑺傛媿璁剧疆", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(bsBeatSettingService.deleteBsBeatSettingByIds(ids));
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/beatSetting/domain/BsBeatSetting.java b/jcdm-main/src/main/java/com/jcdm/main/bs/beatSetting/domain/BsBeatSetting.java
new file mode 100644
index 0000000..62395e2
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/beatSetting/domain/BsBeatSetting.java
@@ -0,0 +1,152 @@
+package com.jcdm.main.bs.beatSetting.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.core.domain.BaseEntity;
+
+/**
+ * 鑺傛媿璁剧疆瀵硅薄 bs_beat_setting
+ * 
+ * @author Yi
+ * @date 2024-01-05
+ */
+public class BsBeatSetting extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 涓婚敭id */
+    private Long id;
+
+    /** 浜у搧缂栫爜 */
+    @Excel(name = "浜у搧缂栫爜")
+    private String productCode;
+
+    /** 浜у搧鍚嶇О */
+    @Excel(name = "浜у搧鍚嶇О")
+    private String productName;
+
+    /** 鑺傛媿 */
+    @Excel(name = "鑺傛媿")
+    private String beat;
+
+    /** 棰勭暀瀛楁1 */
+    @Excel(name = "棰勭暀瀛楁1")
+    private String spareField1;
+
+    /** 棰勭暀瀛楁2 */
+    @Excel(name = "棰勭暀瀛楁2")
+    private String spareField2;
+
+    /** 鍒涘缓鐢ㄦ埛 */
+    @Excel(name = "鍒涘缓鐢ㄦ埛")
+    private String createUser;
+
+    /** 鏇存敼鐢ㄦ埛 */
+    @Excel(name = "鏇存敼鐢ㄦ埛")
+    private String updateUser;
+
+    /** 鏁版嵁鏉ユ簮 */
+    @Excel(name = "鏁版嵁鏉ユ簮")
+    private String dataSource;
+
+    public void setId(Long id) 
+    {
+        this.id = id;
+    }
+
+    public Long getId() 
+    {
+        return id;
+    }
+    public void setProductCode(String productCode) 
+    {
+        this.productCode = productCode;
+    }
+
+    public String getProductCode() 
+    {
+        return productCode;
+    }
+    public void setProductName(String productName) 
+    {
+        this.productName = productName;
+    }
+
+    public String getProductName() 
+    {
+        return productName;
+    }
+    public void setBeat(String beat) 
+    {
+        this.beat = beat;
+    }
+
+    public String getBeat() 
+    {
+        return beat;
+    }
+    public void setSpareField1(String spareField1) 
+    {
+        this.spareField1 = spareField1;
+    }
+
+    public String getSpareField1() 
+    {
+        return spareField1;
+    }
+    public void setSpareField2(String spareField2) 
+    {
+        this.spareField2 = spareField2;
+    }
+
+    public String getSpareField2() 
+    {
+        return spareField2;
+    }
+    public void setCreateUser(String createUser) 
+    {
+        this.createUser = createUser;
+    }
+
+    public String getCreateUser() 
+    {
+        return createUser;
+    }
+    public void setUpdateUser(String updateUser) 
+    {
+        this.updateUser = updateUser;
+    }
+
+    public String getUpdateUser() 
+    {
+        return updateUser;
+    }
+    public void setDataSource(String dataSource) 
+    {
+        this.dataSource = dataSource;
+    }
+
+    public String getDataSource() 
+    {
+        return dataSource;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("productCode", getProductCode())
+            .append("productName", getProductName())
+            .append("beat", getBeat())
+            .append("spareField1", getSpareField1())
+            .append("spareField2", getSpareField2())
+            .append("remark", getRemark())
+            .append("createUser", getCreateUser())
+            .append("createTime", getCreateTime())
+            .append("updateUser", getUpdateUser())
+            .append("updateTime", getUpdateTime())
+            .append("dataSource", getDataSource())
+            .toString();
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/beatSetting/mapper/BsBeatSettingMapper.java b/jcdm-main/src/main/java/com/jcdm/main/bs/beatSetting/mapper/BsBeatSettingMapper.java
new file mode 100644
index 0000000..c5c6918
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/beatSetting/mapper/BsBeatSettingMapper.java
@@ -0,0 +1,61 @@
+package com.jcdm.main.bs.beatSetting.mapper;
+
+import java.util.List;
+import com.jcdm.main.bs.beatSetting.domain.BsBeatSetting;
+
+/**
+ * 鑺傛媿璁剧疆Mapper鎺ュ彛
+ * 
+ * @author Yi
+ * @date 2024-01-05
+ */
+public interface BsBeatSettingMapper 
+{
+    /**
+     * 鏌ヨ鑺傛媿璁剧疆
+     * 
+     * @param id 鑺傛媿璁剧疆涓婚敭
+     * @return 鑺傛媿璁剧疆
+     */
+    public BsBeatSetting selectBsBeatSettingById(Long id);
+
+    /**
+     * 鏌ヨ鑺傛媿璁剧疆鍒楄〃
+     * 
+     * @param bsBeatSetting 鑺傛媿璁剧疆
+     * @return 鑺傛媿璁剧疆闆嗗悎
+     */
+    public List<BsBeatSetting> selectBsBeatSettingList(BsBeatSetting bsBeatSetting);
+
+    /**
+     * 鏂板鑺傛媿璁剧疆
+     * 
+     * @param bsBeatSetting 鑺傛媿璁剧疆
+     * @return 缁撴灉
+     */
+    public int insertBsBeatSetting(BsBeatSetting bsBeatSetting);
+
+    /**
+     * 淇敼鑺傛媿璁剧疆
+     * 
+     * @param bsBeatSetting 鑺傛媿璁剧疆
+     * @return 缁撴灉
+     */
+    public int updateBsBeatSetting(BsBeatSetting bsBeatSetting);
+
+    /**
+     * 鍒犻櫎鑺傛媿璁剧疆
+     * 
+     * @param id 鑺傛媿璁剧疆涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteBsBeatSettingById(Long id);
+
+    /**
+     * 鎵归噺鍒犻櫎鑺傛媿璁剧疆
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteBsBeatSettingByIds(Long[] ids);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/beatSetting/service/IBsBeatSettingService.java b/jcdm-main/src/main/java/com/jcdm/main/bs/beatSetting/service/IBsBeatSettingService.java
new file mode 100644
index 0000000..988143b
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/beatSetting/service/IBsBeatSettingService.java
@@ -0,0 +1,61 @@
+package com.jcdm.main.bs.beatSetting.service;
+
+import java.util.List;
+import com.jcdm.main.bs.beatSetting.domain.BsBeatSetting;
+
+/**
+ * 鑺傛媿璁剧疆Service鎺ュ彛
+ * 
+ * @author Yi
+ * @date 2024-01-05
+ */
+public interface IBsBeatSettingService 
+{
+    /**
+     * 鏌ヨ鑺傛媿璁剧疆
+     * 
+     * @param id 鑺傛媿璁剧疆涓婚敭
+     * @return 鑺傛媿璁剧疆
+     */
+    public BsBeatSetting selectBsBeatSettingById(Long id);
+
+    /**
+     * 鏌ヨ鑺傛媿璁剧疆鍒楄〃
+     * 
+     * @param bsBeatSetting 鑺傛媿璁剧疆
+     * @return 鑺傛媿璁剧疆闆嗗悎
+     */
+    public List<BsBeatSetting> selectBsBeatSettingList(BsBeatSetting bsBeatSetting);
+
+    /**
+     * 鏂板鑺傛媿璁剧疆
+     * 
+     * @param bsBeatSetting 鑺傛媿璁剧疆
+     * @return 缁撴灉
+     */
+    public int insertBsBeatSetting(BsBeatSetting bsBeatSetting);
+
+    /**
+     * 淇敼鑺傛媿璁剧疆
+     * 
+     * @param bsBeatSetting 鑺傛媿璁剧疆
+     * @return 缁撴灉
+     */
+    public int updateBsBeatSetting(BsBeatSetting bsBeatSetting);
+
+    /**
+     * 鎵归噺鍒犻櫎鑺傛媿璁剧疆
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鑺傛媿璁剧疆涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteBsBeatSettingByIds(Long[] ids);
+
+    /**
+     * 鍒犻櫎鑺傛媿璁剧疆淇℃伅
+     * 
+     * @param id 鑺傛媿璁剧疆涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteBsBeatSettingById(Long id);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/beatSetting/service/impl/BsBeatSettingServiceImpl.java b/jcdm-main/src/main/java/com/jcdm/main/bs/beatSetting/service/impl/BsBeatSettingServiceImpl.java
new file mode 100644
index 0000000..a2c19a0
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/beatSetting/service/impl/BsBeatSettingServiceImpl.java
@@ -0,0 +1,96 @@
+package com.jcdm.main.bs.beatSetting.service.impl;
+
+import java.util.List;
+import com.jcdm.common.utils.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.jcdm.main.bs.beatSetting.mapper.BsBeatSettingMapper;
+import com.jcdm.main.bs.beatSetting.domain.BsBeatSetting;
+import com.jcdm.main.bs.beatSetting.service.IBsBeatSettingService;
+
+/**
+ * 鑺傛媿璁剧疆Service涓氬姟灞傚鐞�
+ * 
+ * @author Yi
+ * @date 2024-01-05
+ */
+@Service
+public class BsBeatSettingServiceImpl implements IBsBeatSettingService 
+{
+    @Autowired
+    private BsBeatSettingMapper bsBeatSettingMapper;
+
+    /**
+     * 鏌ヨ鑺傛媿璁剧疆
+     * 
+     * @param id 鑺傛媿璁剧疆涓婚敭
+     * @return 鑺傛媿璁剧疆
+     */
+    @Override
+    public BsBeatSetting selectBsBeatSettingById(Long id)
+    {
+        return bsBeatSettingMapper.selectBsBeatSettingById(id);
+    }
+
+    /**
+     * 鏌ヨ鑺傛媿璁剧疆鍒楄〃
+     * 
+     * @param bsBeatSetting 鑺傛媿璁剧疆
+     * @return 鑺傛媿璁剧疆
+     */
+    @Override
+    public List<BsBeatSetting> selectBsBeatSettingList(BsBeatSetting bsBeatSetting)
+    {
+        return bsBeatSettingMapper.selectBsBeatSettingList(bsBeatSetting);
+    }
+
+    /**
+     * 鏂板鑺傛媿璁剧疆
+     * 
+     * @param bsBeatSetting 鑺傛媿璁剧疆
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertBsBeatSetting(BsBeatSetting bsBeatSetting)
+    {
+        bsBeatSetting.setCreateTime(DateUtils.getNowDate());
+        return bsBeatSettingMapper.insertBsBeatSetting(bsBeatSetting);
+    }
+
+    /**
+     * 淇敼鑺傛媿璁剧疆
+     * 
+     * @param bsBeatSetting 鑺傛媿璁剧疆
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateBsBeatSetting(BsBeatSetting bsBeatSetting)
+    {
+        bsBeatSetting.setUpdateTime(DateUtils.getNowDate());
+        return bsBeatSettingMapper.updateBsBeatSetting(bsBeatSetting);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎鑺傛媿璁剧疆
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鑺傛媿璁剧疆涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteBsBeatSettingByIds(Long[] ids)
+    {
+        return bsBeatSettingMapper.deleteBsBeatSettingByIds(ids);
+    }
+
+    /**
+     * 鍒犻櫎鑺傛媿璁剧疆淇℃伅
+     * 
+     * @param id 鑺傛媿璁剧疆涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteBsBeatSettingById(Long id)
+    {
+        return bsBeatSettingMapper.deleteBsBeatSettingById(id);
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/formula/controller/BsFormulaInfoController.java b/jcdm-main/src/main/java/com/jcdm/main/bs/formula/controller/BsFormulaInfoController.java
new file mode 100644
index 0000000..e29a02e
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/formula/controller/BsFormulaInfoController.java
@@ -0,0 +1,104 @@
+package com.jcdm.main.bs.formula.controller;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.main.bs.formula.domain.BsFormulaInfo;
+import com.jcdm.main.bs.formula.service.IBsFormulaInfoService;
+import com.jcdm.common.utils.poi.ExcelUtil;
+import com.jcdm.common.core.page.TableDataInfo;
+
+/**
+ * 閰嶆柟閰嶇疆Controller
+ * 
+ * @author ruimin
+ * @date 2023-12-26
+ */
+@RestController
+@RequestMapping("/bs/formula")
+public class BsFormulaInfoController extends BaseController
+{
+    @Autowired
+    private IBsFormulaInfoService bsFormulaInfoService;
+
+    /**
+     * 鏌ヨ閰嶆柟閰嶇疆鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('bs:formula:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(BsFormulaInfo bsFormulaInfo)
+    {
+        startPage();
+        List<BsFormulaInfo> list = bsFormulaInfoService.selectBsFormulaInfoList(bsFormulaInfo);
+        return getDataTable(list);
+    }
+
+    /**
+     * 瀵煎嚭閰嶆柟閰嶇疆鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('bs:formula:export')")
+    @Log(title = "閰嶆柟閰嶇疆", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, BsFormulaInfo bsFormulaInfo)
+    {
+        List<BsFormulaInfo> list = bsFormulaInfoService.selectBsFormulaInfoList(bsFormulaInfo);
+        ExcelUtil<BsFormulaInfo> util = new ExcelUtil<BsFormulaInfo>(BsFormulaInfo.class);
+        util.exportExcel(response, list, "閰嶆柟閰嶇疆鏁版嵁");
+    }
+
+    /**
+     * 鑾峰彇閰嶆柟閰嶇疆璇︾粏淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('bs:formula:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(bsFormulaInfoService.selectBsFormulaInfoById(id));
+    }
+
+    /**
+     * 鏂板閰嶆柟閰嶇疆
+     */
+    @PreAuthorize("@ss.hasPermi('bs:formula:add')")
+    @Log(title = "閰嶆柟閰嶇疆", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody BsFormulaInfo bsFormulaInfo)
+    {
+        return toAjax(bsFormulaInfoService.insertBsFormulaInfo(bsFormulaInfo));
+    }
+
+    /**
+     * 淇敼閰嶆柟閰嶇疆
+     */
+    @PreAuthorize("@ss.hasPermi('bs:formula:edit')")
+    @Log(title = "閰嶆柟閰嶇疆", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody BsFormulaInfo bsFormulaInfo)
+    {
+        return toAjax(bsFormulaInfoService.updateBsFormulaInfo(bsFormulaInfo));
+    }
+
+    /**
+     * 鍒犻櫎閰嶆柟閰嶇疆
+     */
+    @PreAuthorize("@ss.hasPermi('bs:formula:remove')")
+    @Log(title = "閰嶆柟閰嶇疆", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(bsFormulaInfoService.deleteBsFormulaInfoByIds(ids));
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/formula/domain/BsFormulaInfo.java b/jcdm-main/src/main/java/com/jcdm/main/bs/formula/domain/BsFormulaInfo.java
new file mode 100644
index 0000000..75b686e
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/formula/domain/BsFormulaInfo.java
@@ -0,0 +1,176 @@
+package com.jcdm.main.bs.formula.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.core.domain.BaseEntity;
+
+/**
+ * 閰嶆柟閰嶇疆瀵硅薄 bs_formula_info
+ * 
+ * @author ruimin
+ * @date 2023-12-26
+ */
+public class BsFormulaInfo extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 涓婚敭id */
+    private Long id;
+
+    /** 閰嶆柟缂栫爜 */
+    @Excel(name = "閰嶆柟缂栫爜")
+    private String formulaCode;
+
+    /** 閰嶆柟鍚嶇О */
+    @Excel(name = "閰嶆柟鍚嶇О")
+    private String formulaName;
+
+    /** 鐘舵�� */
+    @Excel(name = "鐘舵��")
+    private String status;
+
+    /** 浜у搧缂栫爜 */
+    @Excel(name = "浜у搧缂栫爜")
+    private String productCode;
+
+    /** 鍒涘缓鐢ㄦ埛 */
+    @Excel(name = "鍒涘缓鐢ㄦ埛")
+    private String createUser;
+
+    /** 鏇存敼鐢ㄦ埛 */
+    @Excel(name = "鏇存敼鐢ㄦ埛")
+    private String updateUser;
+
+    /** 棰勭暀瀛楁1 */
+    private String spareField1;
+
+    /** 棰勭暀瀛楁2 */
+    private String spareField2;
+
+    /** 棰勭暀瀛楁3 */
+    private String spareField3;
+
+    /** 棰勭暀瀛楁4 */
+    private String spareField4;
+
+    public void setId(Long id) 
+    {
+        this.id = id;
+    }
+
+    public Long getId() 
+    {
+        return id;
+    }
+    public void setFormulaCode(String formulaCode) 
+    {
+        this.formulaCode = formulaCode;
+    }
+
+    public String getFormulaCode() 
+    {
+        return formulaCode;
+    }
+    public void setFormulaName(String formulaName) 
+    {
+        this.formulaName = formulaName;
+    }
+
+    public String getFormulaName() 
+    {
+        return formulaName;
+    }
+    public void setStatus(String status) 
+    {
+        this.status = status;
+    }
+
+    public String getStatus() 
+    {
+        return status;
+    }
+    public void setProductCode(String productCode) 
+    {
+        this.productCode = productCode;
+    }
+
+    public String getProductCode() 
+    {
+        return productCode;
+    }
+    public void setCreateUser(String createUser) 
+    {
+        this.createUser = createUser;
+    }
+
+    public String getCreateUser() 
+    {
+        return createUser;
+    }
+    public void setUpdateUser(String updateUser) 
+    {
+        this.updateUser = updateUser;
+    }
+
+    public String getUpdateUser() 
+    {
+        return updateUser;
+    }
+    public void setSpareField1(String spareField1) 
+    {
+        this.spareField1 = spareField1;
+    }
+
+    public String getSpareField1() 
+    {
+        return spareField1;
+    }
+    public void setSpareField2(String spareField2) 
+    {
+        this.spareField2 = spareField2;
+    }
+
+    public String getSpareField2() 
+    {
+        return spareField2;
+    }
+    public void setSpareField3(String spareField3) 
+    {
+        this.spareField3 = spareField3;
+    }
+
+    public String getSpareField3() 
+    {
+        return spareField3;
+    }
+    public void setSpareField4(String spareField4) 
+    {
+        this.spareField4 = spareField4;
+    }
+
+    public String getSpareField4() 
+    {
+        return spareField4;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("formulaCode", getFormulaCode())
+            .append("formulaName", getFormulaName())
+            .append("status", getStatus())
+            .append("productCode", getProductCode())
+            .append("remark", getRemark())
+            .append("createUser", getCreateUser())
+            .append("createTime", getCreateTime())
+            .append("updateUser", getUpdateUser())
+            .append("updateTime", getUpdateTime())
+            .append("spareField1", getSpareField1())
+            .append("spareField2", getSpareField2())
+            .append("spareField3", getSpareField3())
+            .append("spareField4", getSpareField4())
+            .toString();
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/formula/mapper/BsFormulaInfoMapper.java b/jcdm-main/src/main/java/com/jcdm/main/bs/formula/mapper/BsFormulaInfoMapper.java
new file mode 100644
index 0000000..1105014
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/formula/mapper/BsFormulaInfoMapper.java
@@ -0,0 +1,61 @@
+package com.jcdm.main.bs.formula.mapper;
+
+import java.util.List;
+import com.jcdm.main.bs.formula.domain.BsFormulaInfo;
+
+/**
+ * 閰嶆柟閰嶇疆Mapper鎺ュ彛
+ * 
+ * @author ruimin
+ * @date 2023-12-26
+ */
+public interface BsFormulaInfoMapper 
+{
+    /**
+     * 鏌ヨ閰嶆柟閰嶇疆
+     * 
+     * @param id 閰嶆柟閰嶇疆涓婚敭
+     * @return 閰嶆柟閰嶇疆
+     */
+    public BsFormulaInfo selectBsFormulaInfoById(Long id);
+
+    /**
+     * 鏌ヨ閰嶆柟閰嶇疆鍒楄〃
+     * 
+     * @param bsFormulaInfo 閰嶆柟閰嶇疆
+     * @return 閰嶆柟閰嶇疆闆嗗悎
+     */
+    public List<BsFormulaInfo> selectBsFormulaInfoList(BsFormulaInfo bsFormulaInfo);
+
+    /**
+     * 鏂板閰嶆柟閰嶇疆
+     * 
+     * @param bsFormulaInfo 閰嶆柟閰嶇疆
+     * @return 缁撴灉
+     */
+    public int insertBsFormulaInfo(BsFormulaInfo bsFormulaInfo);
+
+    /**
+     * 淇敼閰嶆柟閰嶇疆
+     * 
+     * @param bsFormulaInfo 閰嶆柟閰嶇疆
+     * @return 缁撴灉
+     */
+    public int updateBsFormulaInfo(BsFormulaInfo bsFormulaInfo);
+
+    /**
+     * 鍒犻櫎閰嶆柟閰嶇疆
+     * 
+     * @param id 閰嶆柟閰嶇疆涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteBsFormulaInfoById(Long id);
+
+    /**
+     * 鎵归噺鍒犻櫎閰嶆柟閰嶇疆
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteBsFormulaInfoByIds(Long[] ids);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/formula/service/IBsFormulaInfoService.java b/jcdm-main/src/main/java/com/jcdm/main/bs/formula/service/IBsFormulaInfoService.java
new file mode 100644
index 0000000..a525e95
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/formula/service/IBsFormulaInfoService.java
@@ -0,0 +1,61 @@
+package com.jcdm.main.bs.formula.service;
+
+import java.util.List;
+import com.jcdm.main.bs.formula.domain.BsFormulaInfo;
+
+/**
+ * 閰嶆柟閰嶇疆Service鎺ュ彛
+ * 
+ * @author ruimin
+ * @date 2023-12-26
+ */
+public interface IBsFormulaInfoService 
+{
+    /**
+     * 鏌ヨ閰嶆柟閰嶇疆
+     * 
+     * @param id 閰嶆柟閰嶇疆涓婚敭
+     * @return 閰嶆柟閰嶇疆
+     */
+    public BsFormulaInfo selectBsFormulaInfoById(Long id);
+
+    /**
+     * 鏌ヨ閰嶆柟閰嶇疆鍒楄〃
+     * 
+     * @param bsFormulaInfo 閰嶆柟閰嶇疆
+     * @return 閰嶆柟閰嶇疆闆嗗悎
+     */
+    public List<BsFormulaInfo> selectBsFormulaInfoList(BsFormulaInfo bsFormulaInfo);
+
+    /**
+     * 鏂板閰嶆柟閰嶇疆
+     * 
+     * @param bsFormulaInfo 閰嶆柟閰嶇疆
+     * @return 缁撴灉
+     */
+    public int insertBsFormulaInfo(BsFormulaInfo bsFormulaInfo);
+
+    /**
+     * 淇敼閰嶆柟閰嶇疆
+     * 
+     * @param bsFormulaInfo 閰嶆柟閰嶇疆
+     * @return 缁撴灉
+     */
+    public int updateBsFormulaInfo(BsFormulaInfo bsFormulaInfo);
+
+    /**
+     * 鎵归噺鍒犻櫎閰嶆柟閰嶇疆
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑閰嶆柟閰嶇疆涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteBsFormulaInfoByIds(Long[] ids);
+
+    /**
+     * 鍒犻櫎閰嶆柟閰嶇疆淇℃伅
+     * 
+     * @param id 閰嶆柟閰嶇疆涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteBsFormulaInfoById(Long id);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/formula/service/impl/BsFormulaInfoServiceImpl.java b/jcdm-main/src/main/java/com/jcdm/main/bs/formula/service/impl/BsFormulaInfoServiceImpl.java
new file mode 100644
index 0000000..00b3873
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/formula/service/impl/BsFormulaInfoServiceImpl.java
@@ -0,0 +1,96 @@
+package com.jcdm.main.bs.formula.service.impl;
+
+import java.util.List;
+import com.jcdm.common.utils.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.jcdm.main.bs.formula.mapper.BsFormulaInfoMapper;
+import com.jcdm.main.bs.formula.domain.BsFormulaInfo;
+import com.jcdm.main.bs.formula.service.IBsFormulaInfoService;
+
+/**
+ * 閰嶆柟閰嶇疆Service涓氬姟灞傚鐞�
+ * 
+ * @author ruimin
+ * @date 2023-12-26
+ */
+@Service
+public class BsFormulaInfoServiceImpl implements IBsFormulaInfoService 
+{
+    @Autowired
+    private BsFormulaInfoMapper bsFormulaInfoMapper;
+
+    /**
+     * 鏌ヨ閰嶆柟閰嶇疆
+     * 
+     * @param id 閰嶆柟閰嶇疆涓婚敭
+     * @return 閰嶆柟閰嶇疆
+     */
+    @Override
+    public BsFormulaInfo selectBsFormulaInfoById(Long id)
+    {
+        return bsFormulaInfoMapper.selectBsFormulaInfoById(id);
+    }
+
+    /**
+     * 鏌ヨ閰嶆柟閰嶇疆鍒楄〃
+     * 
+     * @param bsFormulaInfo 閰嶆柟閰嶇疆
+     * @return 閰嶆柟閰嶇疆
+     */
+    @Override
+    public List<BsFormulaInfo> selectBsFormulaInfoList(BsFormulaInfo bsFormulaInfo)
+    {
+        return bsFormulaInfoMapper.selectBsFormulaInfoList(bsFormulaInfo);
+    }
+
+    /**
+     * 鏂板閰嶆柟閰嶇疆
+     * 
+     * @param bsFormulaInfo 閰嶆柟閰嶇疆
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertBsFormulaInfo(BsFormulaInfo bsFormulaInfo)
+    {
+        bsFormulaInfo.setCreateTime(DateUtils.getNowDate());
+        return bsFormulaInfoMapper.insertBsFormulaInfo(bsFormulaInfo);
+    }
+
+    /**
+     * 淇敼閰嶆柟閰嶇疆
+     * 
+     * @param bsFormulaInfo 閰嶆柟閰嶇疆
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateBsFormulaInfo(BsFormulaInfo bsFormulaInfo)
+    {
+        bsFormulaInfo.setUpdateTime(DateUtils.getNowDate());
+        return bsFormulaInfoMapper.updateBsFormulaInfo(bsFormulaInfo);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎閰嶆柟閰嶇疆
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑閰嶆柟閰嶇疆涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteBsFormulaInfoByIds(Long[] ids)
+    {
+        return bsFormulaInfoMapper.deleteBsFormulaInfoByIds(ids);
+    }
+
+    /**
+     * 鍒犻櫎閰嶆柟閰嶇疆淇℃伅
+     * 
+     * @param id 閰嶆柟閰嶇疆涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteBsFormulaInfoById(Long id)
+    {
+        return bsFormulaInfoMapper.deleteBsFormulaInfoById(id);
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/formulaChild/controller/BsFormulaChildInfoController.java b/jcdm-main/src/main/java/com/jcdm/main/bs/formulaChild/controller/BsFormulaChildInfoController.java
new file mode 100644
index 0000000..7842101
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/formulaChild/controller/BsFormulaChildInfoController.java
@@ -0,0 +1,137 @@
+package com.jcdm.main.bs.formulaChild.controller;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.main.bs.formulaChild.domain.BsFormulaChildInfo;
+import com.jcdm.main.bs.formulaChild.service.IBsFormulaChildInfoService;
+import com.jcdm.common.utils.poi.ExcelUtil;
+import com.jcdm.common.core.page.TableDataInfo;
+
+/**
+ * 閰嶆柟閰嶇疆瀛愪俊鎭疌ontroller
+ * 
+ * @author ruimin
+ * @date 2023-12-26
+ */
+@RestController
+@RequestMapping("/bs/formulaChild")
+public class BsFormulaChildInfoController extends BaseController
+{
+    @Autowired
+    private IBsFormulaChildInfoService bsFormulaChildInfoService;
+
+    /**
+     * 鏌ヨ閰嶆柟閰嶇疆瀛愪俊鎭垪琛�
+     */
+    @PreAuthorize("@ss.hasPermi('bs:formulaChild:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(BsFormulaChildInfo bsFormulaChildInfo)
+    {
+        startPage();
+        List<BsFormulaChildInfo> list = bsFormulaChildInfoService.selectBsFormulaChildInfoList(bsFormulaChildInfo);
+        for (BsFormulaChildInfo formulaChildInfo : list) {
+            formulaChildInfo.setSort(formulaChildInfo.getStepSort());
+            formulaChildInfo.setAddress(formulaChildInfo.getTechRequirement());
+            formulaChildInfo.setImg(formulaChildInfo.getOperationSteps());
+        }
+        return getDataTable(list);
+    }
+
+    /**
+     * 妫�鏌ユ槸鍚﹀彲浠ユ斁琛�
+     */
+    @GetMapping("/releaseCheck")
+    public AjaxResult releaseCheck(BsFormulaChildInfo bsFormulaChildInfo)
+    {
+        List<BsFormulaChildInfo> i = bsFormulaChildInfoService.releaseCheck(bsFormulaChildInfo);
+        return AjaxResult.success(i.size());
+    }
+
+    /**
+     * 鎵爜纭
+     */
+    @GetMapping("/updateResults")
+    public AjaxResult updateResults(BsFormulaChildInfo bsFormulaChildInfo)
+    {
+        return bsFormulaChildInfoService.updateResults(bsFormulaChildInfo);
+    }
+
+    /**
+     * 鏀捐璇风┖鐘舵��
+     */
+    @GetMapping("/workpieceRelease")
+    public AjaxResult workpieceRelease(BsFormulaChildInfo bsFormulaChildInfo)
+    {
+        return bsFormulaChildInfoService.workpieceRelease(bsFormulaChildInfo);
+    }
+
+    /**
+     * 瀵煎嚭閰嶆柟閰嶇疆瀛愪俊鎭垪琛�
+     */
+    @PreAuthorize("@ss.hasPermi('bs:formulaChild:export')")
+    @Log(title = "閰嶆柟閰嶇疆瀛愪俊鎭�", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, BsFormulaChildInfo bsFormulaChildInfo)
+    {
+        List<BsFormulaChildInfo> list = bsFormulaChildInfoService.selectBsFormulaChildInfoList(bsFormulaChildInfo);
+        ExcelUtil<BsFormulaChildInfo> util = new ExcelUtil<BsFormulaChildInfo>(BsFormulaChildInfo.class);
+        util.exportExcel(response, list, "閰嶆柟閰嶇疆瀛愪俊鎭暟鎹�");
+    }
+
+    /**
+     * 鑾峰彇閰嶆柟閰嶇疆瀛愪俊鎭缁嗕俊鎭�
+     */
+    @PreAuthorize("@ss.hasPermi('bs:formulaChild:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(bsFormulaChildInfoService.selectBsFormulaChildInfoById(id));
+    }
+
+    /**
+     * 鏂板閰嶆柟閰嶇疆瀛愪俊鎭�
+     */
+    @PreAuthorize("@ss.hasPermi('bs:formulaChild:add')")
+    @Log(title = "閰嶆柟閰嶇疆瀛愪俊鎭�", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody BsFormulaChildInfo bsFormulaChildInfo)
+    {
+        return toAjax(bsFormulaChildInfoService.insertBsFormulaChildInfo(bsFormulaChildInfo));
+    }
+
+    /**
+     * 淇敼閰嶆柟閰嶇疆瀛愪俊鎭�
+     */
+    @PreAuthorize("@ss.hasPermi('bs:formulaChild:edit')")
+    @Log(title = "閰嶆柟閰嶇疆瀛愪俊鎭�", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody BsFormulaChildInfo bsFormulaChildInfo)
+    {
+        return toAjax(bsFormulaChildInfoService.updateBsFormulaChildInfo(bsFormulaChildInfo));
+    }
+
+    /**
+     * 鍒犻櫎閰嶆柟閰嶇疆瀛愪俊鎭�
+     */
+    @PreAuthorize("@ss.hasPermi('bs:formulaChild:remove')")
+    @Log(title = "閰嶆柟閰嶇疆瀛愪俊鎭�", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(bsFormulaChildInfoService.deleteBsFormulaChildInfoByIds(ids));
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/formulaChild/domain/BsFormulaChildInfo.java b/jcdm-main/src/main/java/com/jcdm/main/bs/formulaChild/domain/BsFormulaChildInfo.java
new file mode 100644
index 0000000..964afed
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/formulaChild/domain/BsFormulaChildInfo.java
@@ -0,0 +1,355 @@
+package com.jcdm.main.bs.formulaChild.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.core.domain.BaseEntity;
+
+/**
+ * 閰嶆柟閰嶇疆瀛愪俊鎭璞� bs_formula_child_info
+ * 
+ * @author ruimin
+ * @date 2023-12-26
+ */
+public class BsFormulaChildInfo extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** id */
+    private Long id;
+
+    /** 杞﹂棿 */
+    @Excel(name = "杞﹂棿")
+    private String workshopCode;
+
+    /** 浜х嚎 */
+    @Excel(name = "浜х嚎")
+    private String lineCode;
+
+    /** 宸ュ簭 */
+    @Excel(name = "宸ュ簭")
+    private String processesCode;
+
+    /** 浜у搧缂栧彿 */
+    @Excel(name = "浜у搧缂栧彿")
+    private String productCode;
+
+    /** 鎿嶄綔鍐呭 */
+    @Excel(name = "鎿嶄綔鍐呭")
+    private String operationSteps;
+
+    /** 鎶�鏈姹� */
+    @Excel(name = "鎶�鏈姹�")
+    private String techRequirement;
+
+    /** 绫诲瀷锛堟壂鎻忎骇鍝佹潯鐮�1銆佹壂鎻忕墿鏂欐潯鐮�2銆佹嫥绱х被3锛� */
+    @Excel(name = "绫诲瀷", readConverterExp = "鎵�=鎻忎骇鍝佹潯鐮�1銆佹壂鎻忕墿鏂欐潯鐮�2銆佹嫥绱х被3")
+    private String operationType;
+
+    /** 鎺掑簭 */
+    @Excel(name = "鎺掑簭")
+    private String stepSort;
+
+    /** 鍙傛暟缂栫爜 */
+    @Excel(name = "鍙傛暟缂栫爜")
+    private String paramCode;
+
+    /** 鐗╂枡缂栫爜 */
+    @Excel(name = "鐗╂枡缂栫爜")
+    private String materialCode;
+
+    /** 閰嶆柟缂栫爜 */
+    @Excel(name = "閰嶆柟缂栫爜")
+    private String formulaCode;
+
+    /** 鍥剧墖 */
+    @Excel(name = "鍥剧墖")
+    private String picture;
+
+    /** 澶囨敞 */
+    @Excel(name = "澶囨敞")
+    private String remarks;
+
+    /** 鍒涘缓鐢ㄦ埛 */
+    @Excel(name = "鍒涘缓鐢ㄦ埛")
+    private String createUser;
+
+    /** 鏇存敼鐢ㄦ埛 */
+    @Excel(name = "鏇存敼鐢ㄦ埛")
+    private String updateUser;
+
+    /** 棰勭暀瀛楁1 */
+    private String spareField1;
+
+    /** 棰勭暀瀛楁2 */
+    private String spareField2;
+
+    /** 棰勭暀瀛楁3 */
+    private String spareField3;
+
+    /** 棰勭暀瀛楁4 */
+    private String spareField4;
+
+    /** 閲囬泦鏁版嵁 */
+    @Excel(name = "閲囬泦鏁版嵁")
+    private String collectData;
+
+    /** 缁撴灉 */
+    @Excel(name = "缁撴灉")
+    private String results;
+
+    private String sort;
+
+    private String address;
+
+    private String img;
+
+    public String getCollectData() {
+        return collectData;
+    }
+
+    public void setCollectData(String collectData) {
+        this.collectData = collectData;
+    }
+
+    public String getResults() {
+        return results;
+    }
+
+    public void setResults(String results) {
+        this.results = results;
+    }
+
+    public String getSort() {
+        return sort;
+    }
+
+    public void setSort(String sort) {
+        this.sort = sort;
+    }
+
+    public String getAddress() {
+        return address;
+    }
+
+    public void setAddress(String address) {
+        this.address = address;
+    }
+
+    public String getImg() {
+        return img;
+    }
+
+    public void setImg(String img) {
+        this.img = img;
+    }
+
+    public void setId(Long id)
+    {
+        this.id = id;
+    }
+
+    public Long getId() 
+    {
+        return id;
+    }
+    public void setWorkshopCode(String workshopCode) 
+    {
+        this.workshopCode = workshopCode;
+    }
+
+    public String getWorkshopCode() 
+    {
+        return workshopCode;
+    }
+    public void setLineCode(String lineCode) 
+    {
+        this.lineCode = lineCode;
+    }
+
+    public String getLineCode() 
+    {
+        return lineCode;
+    }
+    public void setProcessesCode(String processesCode) 
+    {
+        this.processesCode = processesCode;
+    }
+
+    public String getProcessesCode() 
+    {
+        return processesCode;
+    }
+    public void setProductCode(String productCode) 
+    {
+        this.productCode = productCode;
+    }
+
+    public String getProductCode() 
+    {
+        return productCode;
+    }
+    public void setOperationSteps(String operationSteps) 
+    {
+        this.operationSteps = operationSteps;
+    }
+
+    public String getOperationSteps() 
+    {
+        return operationSteps;
+    }
+    public void setTechRequirement(String techRequirement) 
+    {
+        this.techRequirement = techRequirement;
+    }
+
+    public String getTechRequirement() 
+    {
+        return techRequirement;
+    }
+    public void setOperationType(String operationType) 
+    {
+        this.operationType = operationType;
+    }
+
+    public String getOperationType() 
+    {
+        return operationType;
+    }
+    public void setStepSort(String stepSort) 
+    {
+        this.stepSort = stepSort;
+    }
+
+    public String getStepSort() 
+    {
+        return stepSort;
+    }
+    public void setParamCode(String paramCode) 
+    {
+        this.paramCode = paramCode;
+    }
+
+    public String getParamCode() 
+    {
+        return paramCode;
+    }
+    public void setMaterialCode(String materialCode) 
+    {
+        this.materialCode = materialCode;
+    }
+
+    public String getMaterialCode() 
+    {
+        return materialCode;
+    }
+    public void setFormulaCode(String formulaCode) 
+    {
+        this.formulaCode = formulaCode;
+    }
+
+    public String getFormulaCode() 
+    {
+        return formulaCode;
+    }
+    public void setPicture(String picture) 
+    {
+        this.picture = picture;
+    }
+
+    public String getPicture() 
+    {
+        return picture;
+    }
+    public void setRemarks(String remarks) 
+    {
+        this.remarks = remarks;
+    }
+
+    public String getRemarks() 
+    {
+        return remarks;
+    }
+    public void setCreateUser(String createUser) 
+    {
+        this.createUser = createUser;
+    }
+
+    public String getCreateUser() 
+    {
+        return createUser;
+    }
+    public void setUpdateUser(String updateUser) 
+    {
+        this.updateUser = updateUser;
+    }
+
+    public String getUpdateUser() 
+    {
+        return updateUser;
+    }
+    public void setSpareField1(String spareField1) 
+    {
+        this.spareField1 = spareField1;
+    }
+
+    public String getSpareField1() 
+    {
+        return spareField1;
+    }
+    public void setSpareField2(String spareField2) 
+    {
+        this.spareField2 = spareField2;
+    }
+
+    public String getSpareField2() 
+    {
+        return spareField2;
+    }
+    public void setSpareField3(String spareField3) 
+    {
+        this.spareField3 = spareField3;
+    }
+
+    public String getSpareField3() 
+    {
+        return spareField3;
+    }
+    public void setSpareField4(String spareField4) 
+    {
+        this.spareField4 = spareField4;
+    }
+
+    public String getSpareField4() 
+    {
+        return spareField4;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("workshopCode", getWorkshopCode())
+            .append("lineCode", getLineCode())
+            .append("processesCode", getProcessesCode())
+            .append("productCode", getProductCode())
+            .append("operationSteps", getOperationSteps())
+            .append("techRequirement", getTechRequirement())
+            .append("operationType", getOperationType())
+            .append("stepSort", getStepSort())
+            .append("paramCode", getParamCode())
+            .append("materialCode", getMaterialCode())
+            .append("formulaCode", getFormulaCode())
+            .append("picture", getPicture())
+            .append("remarks", getRemarks())
+            .append("createUser", getCreateUser())
+            .append("createTime", getCreateTime())
+            .append("updateUser", getUpdateUser())
+            .append("updateTime", getUpdateTime())
+            .append("spareField1", getSpareField1())
+            .append("spareField2", getSpareField2())
+            .append("spareField3", getSpareField3())
+            .append("spareField4", getSpareField4())
+            .toString();
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/formulaChild/mapper/BsFormulaChildInfoMapper.java b/jcdm-main/src/main/java/com/jcdm/main/bs/formulaChild/mapper/BsFormulaChildInfoMapper.java
new file mode 100644
index 0000000..695115c
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/formulaChild/mapper/BsFormulaChildInfoMapper.java
@@ -0,0 +1,67 @@
+package com.jcdm.main.bs.formulaChild.mapper;
+
+import java.util.List;
+import com.jcdm.main.bs.formulaChild.domain.BsFormulaChildInfo;
+
+/**
+ * 閰嶆柟閰嶇疆瀛愪俊鎭疢apper鎺ュ彛
+ * 
+ * @author ruimin
+ * @date 2023-12-26
+ */
+public interface BsFormulaChildInfoMapper 
+{
+    /**
+     * 鏌ヨ閰嶆柟閰嶇疆瀛愪俊鎭�
+     * 
+     * @param id 閰嶆柟閰嶇疆瀛愪俊鎭富閿�
+     * @return 閰嶆柟閰嶇疆瀛愪俊鎭�
+     */
+    public BsFormulaChildInfo selectBsFormulaChildInfoById(Long id);
+
+    /**
+     * 鏌ヨ閰嶆柟閰嶇疆瀛愪俊鎭垪琛�
+     * 
+     * @param bsFormulaChildInfo 閰嶆柟閰嶇疆瀛愪俊鎭�
+     * @return 閰嶆柟閰嶇疆瀛愪俊鎭泦鍚�
+     */
+    public List<BsFormulaChildInfo> selectBsFormulaChildInfoList(BsFormulaChildInfo bsFormulaChildInfo);
+
+    /**
+     * 鏂板閰嶆柟閰嶇疆瀛愪俊鎭�
+     * 
+     * @param bsFormulaChildInfo 閰嶆柟閰嶇疆瀛愪俊鎭�
+     * @return 缁撴灉
+     */
+    public int insertBsFormulaChildInfo(BsFormulaChildInfo bsFormulaChildInfo);
+
+    /**
+     * 淇敼閰嶆柟閰嶇疆瀛愪俊鎭�
+     * 
+     * @param bsFormulaChildInfo 閰嶆柟閰嶇疆瀛愪俊鎭�
+     * @return 缁撴灉
+     */
+    public int updateBsFormulaChildInfo(BsFormulaChildInfo bsFormulaChildInfo);
+
+    /**
+     * 鍒犻櫎閰嶆柟閰嶇疆瀛愪俊鎭�
+     * 
+     * @param id 閰嶆柟閰嶇疆瀛愪俊鎭富閿�
+     * @return 缁撴灉
+     */
+    public int deleteBsFormulaChildInfoById(Long id);
+
+    /**
+     * 鎵归噺鍒犻櫎閰嶆柟閰嶇疆瀛愪俊鎭�
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteBsFormulaChildInfoByIds(Long[] ids);
+
+    BsFormulaChildInfo selectBsFormulaChildInfoByTypeTopOne(BsFormulaChildInfo bsFormulaChildInfo);
+
+    List<BsFormulaChildInfo> releaseCheck(BsFormulaChildInfo bsFormulaChildInfo);
+
+    void workpieceRelease(BsFormulaChildInfo bsFormulaChildInfo);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/formulaChild/service/IBsFormulaChildInfoService.java b/jcdm-main/src/main/java/com/jcdm/main/bs/formulaChild/service/IBsFormulaChildInfoService.java
new file mode 100644
index 0000000..5c85566
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/formulaChild/service/IBsFormulaChildInfoService.java
@@ -0,0 +1,71 @@
+package com.jcdm.main.bs.formulaChild.service;
+
+import java.util.List;
+
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.main.bs.formulaChild.domain.BsFormulaChildInfo;
+
+/**
+ * 閰嶆柟閰嶇疆瀛愪俊鎭疭ervice鎺ュ彛
+ * 
+ * @author ruimin
+ * @date 2023-12-26
+ */
+public interface IBsFormulaChildInfoService 
+{
+    /**
+     * 鏌ヨ閰嶆柟閰嶇疆瀛愪俊鎭�
+     * 
+     * @param id 閰嶆柟閰嶇疆瀛愪俊鎭富閿�
+     * @return 閰嶆柟閰嶇疆瀛愪俊鎭�
+     */
+    public BsFormulaChildInfo selectBsFormulaChildInfoById(Long id);
+
+    /**
+     * 鏌ヨ閰嶆柟閰嶇疆瀛愪俊鎭垪琛�
+     * 
+     * @param bsFormulaChildInfo 閰嶆柟閰嶇疆瀛愪俊鎭�
+     * @return 閰嶆柟閰嶇疆瀛愪俊鎭泦鍚�
+     */
+    public List<BsFormulaChildInfo> selectBsFormulaChildInfoList(BsFormulaChildInfo bsFormulaChildInfo);
+
+    /**
+     * 鏂板閰嶆柟閰嶇疆瀛愪俊鎭�
+     * 
+     * @param bsFormulaChildInfo 閰嶆柟閰嶇疆瀛愪俊鎭�
+     * @return 缁撴灉
+     */
+    public int insertBsFormulaChildInfo(BsFormulaChildInfo bsFormulaChildInfo);
+
+    /**
+     * 淇敼閰嶆柟閰嶇疆瀛愪俊鎭�
+     * 
+     * @param bsFormulaChildInfo 閰嶆柟閰嶇疆瀛愪俊鎭�
+     * @return 缁撴灉
+     */
+    public int updateBsFormulaChildInfo(BsFormulaChildInfo bsFormulaChildInfo);
+
+    /**
+     * 鎵归噺鍒犻櫎閰嶆柟閰嶇疆瀛愪俊鎭�
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑閰嶆柟閰嶇疆瀛愪俊鎭富閿泦鍚�
+     * @return 缁撴灉
+     */
+    public int deleteBsFormulaChildInfoByIds(Long[] ids);
+
+    /**
+     * 鍒犻櫎閰嶆柟閰嶇疆瀛愪俊鎭俊鎭�
+     * 
+     * @param id 閰嶆柟閰嶇疆瀛愪俊鎭富閿�
+     * @return 缁撴灉
+     */
+    public int deleteBsFormulaChildInfoById(Long id);
+
+    public BsFormulaChildInfo selectBsFormulaChildInfoByTypeTopOne(String type,String productCode,String processesCode);
+
+    List<BsFormulaChildInfo> releaseCheck(BsFormulaChildInfo bsFormulaChildInfo);
+
+    AjaxResult updateResults(BsFormulaChildInfo bsFormulaChildInfo);
+
+    AjaxResult workpieceRelease(BsFormulaChildInfo bsFormulaChildInfo);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/formulaChild/service/impl/BsFormulaChildInfoServiceImpl.java b/jcdm-main/src/main/java/com/jcdm/main/bs/formulaChild/service/impl/BsFormulaChildInfoServiceImpl.java
new file mode 100644
index 0000000..09972b8
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/formulaChild/service/impl/BsFormulaChildInfoServiceImpl.java
@@ -0,0 +1,130 @@
+package com.jcdm.main.bs.formulaChild.service.impl;
+
+import java.util.List;
+
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.utils.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.jcdm.main.bs.formulaChild.mapper.BsFormulaChildInfoMapper;
+import com.jcdm.main.bs.formulaChild.domain.BsFormulaChildInfo;
+import com.jcdm.main.bs.formulaChild.service.IBsFormulaChildInfoService;
+
+/**
+ * 閰嶆柟閰嶇疆瀛愪俊鎭疭ervice涓氬姟灞傚鐞�
+ * 
+ * @author ruimin
+ * @date 2023-12-26
+ */
+@Service
+public class BsFormulaChildInfoServiceImpl implements IBsFormulaChildInfoService 
+{
+    @Autowired
+    private BsFormulaChildInfoMapper bsFormulaChildInfoMapper;
+
+    /**
+     * 鏌ヨ閰嶆柟閰嶇疆瀛愪俊鎭�
+     * 
+     * @param id 閰嶆柟閰嶇疆瀛愪俊鎭富閿�
+     * @return 閰嶆柟閰嶇疆瀛愪俊鎭�
+     */
+    @Override
+    public BsFormulaChildInfo selectBsFormulaChildInfoById(Long id)
+    {
+        return bsFormulaChildInfoMapper.selectBsFormulaChildInfoById(id);
+    }
+
+    /**
+     * 鏌ヨ閰嶆柟閰嶇疆瀛愪俊鎭垪琛�
+     * 
+     * @param bsFormulaChildInfo 閰嶆柟閰嶇疆瀛愪俊鎭�
+     * @return 閰嶆柟閰嶇疆瀛愪俊鎭�
+     */
+    @Override
+    public List<BsFormulaChildInfo> selectBsFormulaChildInfoList(BsFormulaChildInfo bsFormulaChildInfo)
+    {
+        return bsFormulaChildInfoMapper.selectBsFormulaChildInfoList(bsFormulaChildInfo);
+    }
+
+    /**
+     * 鏂板閰嶆柟閰嶇疆瀛愪俊鎭�
+     * 
+     * @param bsFormulaChildInfo 閰嶆柟閰嶇疆瀛愪俊鎭�
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertBsFormulaChildInfo(BsFormulaChildInfo bsFormulaChildInfo)
+    {
+        bsFormulaChildInfo.setCreateTime(DateUtils.getNowDate());
+        return bsFormulaChildInfoMapper.insertBsFormulaChildInfo(bsFormulaChildInfo);
+    }
+
+    /**
+     * 淇敼閰嶆柟閰嶇疆瀛愪俊鎭�
+     * 
+     * @param bsFormulaChildInfo 閰嶆柟閰嶇疆瀛愪俊鎭�
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateBsFormulaChildInfo(BsFormulaChildInfo bsFormulaChildInfo)
+    {
+        bsFormulaChildInfo.setUpdateTime(DateUtils.getNowDate());
+        return bsFormulaChildInfoMapper.updateBsFormulaChildInfo(bsFormulaChildInfo);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎閰嶆柟閰嶇疆瀛愪俊鎭�
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑閰嶆柟閰嶇疆瀛愪俊鎭富閿�
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteBsFormulaChildInfoByIds(Long[] ids)
+    {
+        return bsFormulaChildInfoMapper.deleteBsFormulaChildInfoByIds(ids);
+    }
+
+    /**
+     * 鍒犻櫎閰嶆柟閰嶇疆瀛愪俊鎭俊鎭�
+     * 
+     * @param id 閰嶆柟閰嶇疆瀛愪俊鎭富閿�
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteBsFormulaChildInfoById(Long id)
+    {
+        return bsFormulaChildInfoMapper.deleteBsFormulaChildInfoById(id);
+    }
+
+    @Override
+    public BsFormulaChildInfo selectBsFormulaChildInfoByTypeTopOne(String type,String productCode,String processesCode) {
+        BsFormulaChildInfo info = new BsFormulaChildInfo();
+        info.setOperationType(type);
+        info.setProcessesCode(processesCode);
+        info.setProductCode(productCode);
+        return bsFormulaChildInfoMapper.selectBsFormulaChildInfoByTypeTopOne(info);
+    }
+
+    @Override
+    public List<BsFormulaChildInfo> releaseCheck(BsFormulaChildInfo bsFormulaChildInfo) {
+        return bsFormulaChildInfoMapper.releaseCheck(bsFormulaChildInfo);
+    }
+
+    @Override
+    public AjaxResult updateResults(BsFormulaChildInfo bsFormulaChildInfo) {
+        List<BsFormulaChildInfo> bsFormulaChildInfos = bsFormulaChildInfoMapper.selectBsFormulaChildInfoList(bsFormulaChildInfo);
+        if(bsFormulaChildInfos.size()>0){
+            bsFormulaChildInfos.get(0).setResults("OK");
+            bsFormulaChildInfoMapper.updateBsFormulaChildInfo(bsFormulaChildInfos.get(0));
+        }else {
+            return AjaxResult.error("闈炴湰宸ヤ綅鐗╂枡锛岃閲嶆柊鎵弿");
+        }
+        return AjaxResult.success("鎴愬姛");
+    }
+
+    @Override
+    public AjaxResult workpieceRelease(BsFormulaChildInfo bsFormulaChildInfo) {
+        bsFormulaChildInfoMapper.workpieceRelease(bsFormulaChildInfo);
+        return AjaxResult.success();
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/lineInfo/controller/BsLineInfoController.java b/jcdm-main/src/main/java/com/jcdm/main/bs/lineInfo/controller/BsLineInfoController.java
new file mode 100644
index 0000000..450d06f
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/lineInfo/controller/BsLineInfoController.java
@@ -0,0 +1,104 @@
+package com.jcdm.main.bs.lineInfo.controller;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.main.bs.lineInfo.domain.BsLineInfo;
+import com.jcdm.main.bs.lineInfo.service.IBsLineInfoService;
+import com.jcdm.common.utils.poi.ExcelUtil;
+import com.jcdm.common.core.page.TableDataInfo;
+
+/**
+ * 浜х嚎淇℃伅Controller
+ *
+ * @author Yi
+ * @date 2023-12-09
+ */
+@RestController
+@RequestMapping("/bs/lineInfo")
+public class BsLineInfoController extends BaseController
+{
+    @Autowired
+    private IBsLineInfoService bsLineInfoService;
+
+    /**
+     * 鏌ヨ浜х嚎淇℃伅鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('bs:lineInfo:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(BsLineInfo bsLineInfo)
+    {
+        startPage();
+        List<BsLineInfo> list = bsLineInfoService.selectBsLineInfoList(bsLineInfo);
+        return getDataTable(list);
+    }
+
+    /**
+     * 瀵煎嚭浜х嚎淇℃伅鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('bs:lineInfo:export')")
+    @Log(title = "浜х嚎淇℃伅", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, BsLineInfo bsLineInfo)
+    {
+        List<BsLineInfo> list = bsLineInfoService.selectBsLineInfoList(bsLineInfo);
+        ExcelUtil<BsLineInfo> util = new ExcelUtil<BsLineInfo>(BsLineInfo.class);
+        util.exportExcel(response, list, "浜х嚎淇℃伅鏁版嵁");
+    }
+
+    /**
+     * 鑾峰彇浜х嚎淇℃伅璇︾粏淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('bs:lineInfo:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(bsLineInfoService.selectBsLineInfoById(id));
+    }
+
+    /**
+     * 鏂板浜х嚎淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('bs:lineInfo:add')")
+    @Log(title = "浜х嚎淇℃伅", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody BsLineInfo bsLineInfo)
+    {
+        return toAjax(bsLineInfoService.insertBsLineInfo(bsLineInfo));
+    }
+
+    /**
+     * 淇敼浜х嚎淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('bs:lineInfo:edit')")
+    @Log(title = "浜х嚎淇℃伅", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody BsLineInfo bsLineInfo)
+    {
+        return toAjax(bsLineInfoService.updateBsLineInfo(bsLineInfo));
+    }
+
+    /**
+     * 鍒犻櫎浜х嚎淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('bs:lineInfo:remove')")
+    @Log(title = "浜х嚎淇℃伅", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(bsLineInfoService.deleteBsLineInfoByIds(ids));
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/lineInfo/domain/BsLineInfo.java b/jcdm-main/src/main/java/com/jcdm/main/bs/lineInfo/domain/BsLineInfo.java
new file mode 100644
index 0000000..6bee7a1
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/lineInfo/domain/BsLineInfo.java
@@ -0,0 +1,190 @@
+package com.jcdm.main.bs.lineInfo.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.core.domain.BaseEntity;
+
+/**
+ * 浜х嚎淇℃伅瀵硅薄 bs_line_info
+ *
+ * @author Yi
+ * @date 2023-12-09
+ */
+public class BsLineInfo extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 涓婚敭id */
+    private Long id;
+
+    /** 浜х嚎缂栧彿 */
+    @Excel(name = "浜х嚎缂栧彿")
+    private String lineCode;
+
+    /** 浜х嚎鍚嶇О */
+    @Excel(name = "浜х嚎鍚嶇О")
+    private String lineName;
+
+    /** 杞﹂棿缂栧彿 */
+    @Excel(name = "杞﹂棿缂栧彿")
+    private String workshopCode;
+
+    /** 宸ヤ綔鏃ュ巻 */
+    @Excel(name = "宸ヤ綔鏃ュ巻")
+    private String workCalendar;
+
+    /** 棰勭暀瀛楁1 */
+    @Excel(name = "棰勭暀瀛楁1")
+    private String spareField1;
+
+    /** 棰勭暀瀛楁2 */
+    @Excel(name = "棰勭暀瀛楁2")
+    private String spareField2;
+
+    /** 澶囨敞 */
+    @Excel(name = "澶囨敞")
+    private String remarks;
+
+    /** 鍒涘缓鐢ㄦ埛 */
+    @Excel(name = "鍒涘缓鐢ㄦ埛")
+    private String createUser;
+
+    /** 鏇存敼鐢ㄦ埛 */
+    @Excel(name = "鏇存敼鐢ㄦ埛")
+    private String updateUser;
+
+    @Excel(name = "杞﹂棿鍚嶇О")
+    private String workshopName;
+    @Excel(name = "鐘舵��")
+    private String status;
+
+    public void setId(Long id)
+    {
+        this.id = id;
+    }
+
+    public Long getId()
+    {
+        return id;
+    }
+    public void setLineCode(String lineCode)
+    {
+        this.lineCode = lineCode;
+    }
+
+    public String getLineCode()
+    {
+        return lineCode;
+    }
+    public void setLineName(String lineName)
+    {
+        this.lineName = lineName;
+    }
+
+    public String getLineName()
+    {
+        return lineName;
+    }
+    public void setWorkshopName(String workshopName)
+    {
+        this.workshopName = workshopName;
+    }
+
+    public String getWorkshopName()
+    {
+        return workshopName;
+    }
+    public void setWorkshopCode(String workshopCode)
+    {
+        this.workshopCode = workshopCode;
+    }
+
+    public String getWorkshopCode()
+    {
+        return workshopCode;
+    }
+    public void setWorkCalendar(String workCalendar)
+    {
+        this.workCalendar = workCalendar;
+    }
+
+    public String getWorkCalendar()
+    {
+        return workCalendar;
+    }
+    public void setStatus(String status)
+    {
+        this.status = status;
+    }
+
+    public String getStatus()
+    {
+        return status;
+    }
+    public void setSpareField1(String spareField1)
+    {
+        this.spareField1 = spareField1;
+    }
+
+    public String getSpareField1()
+    {
+        return spareField1;
+    }
+    public void setSpareField2(String spareField2)
+    {
+        this.spareField2 = spareField2;
+    }
+
+    public String getSpareField2()
+    {
+        return spareField2;
+    }
+    public void setRemarks(String remarks)
+    {
+        this.remarks = remarks;
+    }
+
+    public String getRemarks()
+    {
+        return remarks;
+    }
+    public void setCreateUser(String createUser)
+    {
+        this.createUser = createUser;
+    }
+
+    public String getCreateUser()
+    {
+        return createUser;
+    }
+    public void setUpdateUser(String updateUser)
+    {
+        this.updateUser = updateUser;
+    }
+
+    public String getUpdateUser()
+    {
+        return updateUser;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("lineCode", getLineCode())
+            .append("lineName", getLineName())
+            .append("workshopCode", getWorkshopCode())
+            .append("workCalendar", getWorkCalendar())
+            .append("spareField1", getSpareField1())
+            .append("spareField2", getSpareField2())
+            .append("remarks", getRemarks())
+            .append("createUser", getCreateUser())
+            .append("createTime", getCreateTime())
+            .append("updateUser", getUpdateUser())
+            .append("updateTime", getUpdateTime())
+            .append("workshopName", getWorkshopName())
+            .append("status", getStatus())
+            .toString();
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/lineInfo/mapper/BsLineInfoMapper.java b/jcdm-main/src/main/java/com/jcdm/main/bs/lineInfo/mapper/BsLineInfoMapper.java
new file mode 100644
index 0000000..40c3c7d
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/lineInfo/mapper/BsLineInfoMapper.java
@@ -0,0 +1,61 @@
+package com.jcdm.main.bs.lineInfo.mapper;
+
+import java.util.List;
+import com.jcdm.main.bs.lineInfo.domain.BsLineInfo;
+
+/**
+ * 浜х嚎淇℃伅Mapper鎺ュ彛
+ * 
+ * @author Yi
+ * @date 2023-12-09
+ */
+public interface BsLineInfoMapper 
+{
+    /**
+     * 鏌ヨ浜х嚎淇℃伅
+     * 
+     * @param id 浜х嚎淇℃伅涓婚敭
+     * @return 浜х嚎淇℃伅
+     */
+    public BsLineInfo selectBsLineInfoById(Long id);
+
+    /**
+     * 鏌ヨ浜х嚎淇℃伅鍒楄〃
+     * 
+     * @param bsLineInfo 浜х嚎淇℃伅
+     * @return 浜х嚎淇℃伅闆嗗悎
+     */
+    public List<BsLineInfo> selectBsLineInfoList(BsLineInfo bsLineInfo);
+
+    /**
+     * 鏂板浜х嚎淇℃伅
+     * 
+     * @param bsLineInfo 浜х嚎淇℃伅
+     * @return 缁撴灉
+     */
+    public int insertBsLineInfo(BsLineInfo bsLineInfo);
+
+    /**
+     * 淇敼浜х嚎淇℃伅
+     * 
+     * @param bsLineInfo 浜х嚎淇℃伅
+     * @return 缁撴灉
+     */
+    public int updateBsLineInfo(BsLineInfo bsLineInfo);
+
+    /**
+     * 鍒犻櫎浜х嚎淇℃伅
+     * 
+     * @param id 浜х嚎淇℃伅涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteBsLineInfoById(Long id);
+
+    /**
+     * 鎵归噺鍒犻櫎浜х嚎淇℃伅
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteBsLineInfoByIds(Long[] ids);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/lineInfo/service/IBsLineInfoService.java b/jcdm-main/src/main/java/com/jcdm/main/bs/lineInfo/service/IBsLineInfoService.java
new file mode 100644
index 0000000..d96dc2d
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/lineInfo/service/IBsLineInfoService.java
@@ -0,0 +1,61 @@
+package com.jcdm.main.bs.lineInfo.service;
+
+import java.util.List;
+import com.jcdm.main.bs.lineInfo.domain.BsLineInfo;
+
+/**
+ * 浜х嚎淇℃伅Service鎺ュ彛
+ * 
+ * @author Yi
+ * @date 2023-12-09
+ */
+public interface IBsLineInfoService 
+{
+    /**
+     * 鏌ヨ浜х嚎淇℃伅
+     * 
+     * @param id 浜х嚎淇℃伅涓婚敭
+     * @return 浜х嚎淇℃伅
+     */
+    public BsLineInfo selectBsLineInfoById(Long id);
+
+    /**
+     * 鏌ヨ浜х嚎淇℃伅鍒楄〃
+     * 
+     * @param bsLineInfo 浜х嚎淇℃伅
+     * @return 浜х嚎淇℃伅闆嗗悎
+     */
+    public List<BsLineInfo> selectBsLineInfoList(BsLineInfo bsLineInfo);
+
+    /**
+     * 鏂板浜х嚎淇℃伅
+     * 
+     * @param bsLineInfo 浜х嚎淇℃伅
+     * @return 缁撴灉
+     */
+    public int insertBsLineInfo(BsLineInfo bsLineInfo);
+
+    /**
+     * 淇敼浜х嚎淇℃伅
+     * 
+     * @param bsLineInfo 浜х嚎淇℃伅
+     * @return 缁撴灉
+     */
+    public int updateBsLineInfo(BsLineInfo bsLineInfo);
+
+    /**
+     * 鎵归噺鍒犻櫎浜х嚎淇℃伅
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑浜х嚎淇℃伅涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteBsLineInfoByIds(Long[] ids);
+
+    /**
+     * 鍒犻櫎浜х嚎淇℃伅淇℃伅
+     * 
+     * @param id 浜х嚎淇℃伅涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteBsLineInfoById(Long id);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/lineInfo/service/impl/BsLineInfoServiceImpl.java b/jcdm-main/src/main/java/com/jcdm/main/bs/lineInfo/service/impl/BsLineInfoServiceImpl.java
new file mode 100644
index 0000000..c396b16
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/lineInfo/service/impl/BsLineInfoServiceImpl.java
@@ -0,0 +1,100 @@
+package com.jcdm.main.bs.lineInfo.service.impl;
+
+import java.util.List;
+import com.jcdm.common.utils.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.jcdm.main.bs.lineInfo.mapper.BsLineInfoMapper;
+import com.jcdm.main.bs.lineInfo.domain.BsLineInfo;
+import com.jcdm.main.bs.lineInfo.service.IBsLineInfoService;
+
+import static org.apache.commons.lang3.SystemUtils.getUserName;
+
+/**
+ * 浜х嚎淇℃伅Service涓氬姟灞傚鐞�
+ * 
+ * @author Yi
+ * @date 2023-12-09
+ */
+@Service
+public class BsLineInfoServiceImpl implements IBsLineInfoService 
+{
+    @Autowired
+    private BsLineInfoMapper bsLineInfoMapper;
+
+    /**
+     * 鏌ヨ浜х嚎淇℃伅
+     * 
+     * @param id 浜х嚎淇℃伅涓婚敭
+     * @return 浜х嚎淇℃伅
+     */
+    @Override
+    public BsLineInfo selectBsLineInfoById(Long id)
+    {
+        return bsLineInfoMapper.selectBsLineInfoById(id);
+    }
+
+    /**
+     * 鏌ヨ浜х嚎淇℃伅鍒楄〃
+     * 
+     * @param bsLineInfo 浜х嚎淇℃伅
+     * @return 浜х嚎淇℃伅
+     */
+    @Override
+    public List<BsLineInfo> selectBsLineInfoList(BsLineInfo bsLineInfo)
+    {
+        return bsLineInfoMapper.selectBsLineInfoList(bsLineInfo);
+    }
+
+    /**
+     * 鏂板浜х嚎淇℃伅
+     * 
+     * @param bsLineInfo 浜х嚎淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertBsLineInfo(BsLineInfo bsLineInfo)
+    {
+        bsLineInfo.setCreateTime(DateUtils.getNowDate());
+        bsLineInfo.setCreateUser(getUserName());
+        return bsLineInfoMapper.insertBsLineInfo(bsLineInfo);
+    }
+
+    /**
+     * 淇敼浜х嚎淇℃伅
+     * 
+     * @param bsLineInfo 浜х嚎淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateBsLineInfo(BsLineInfo bsLineInfo)
+    {
+        bsLineInfo.setUpdateTime(DateUtils.getNowDate());
+        bsLineInfo.setUpdateUser(getUserName());
+        return bsLineInfoMapper.updateBsLineInfo(bsLineInfo);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎浜х嚎淇℃伅
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑浜х嚎淇℃伅涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteBsLineInfoByIds(Long[] ids)
+    {
+        return bsLineInfoMapper.deleteBsLineInfoByIds(ids);
+    }
+
+    /**
+     * 鍒犻櫎浜х嚎淇℃伅淇℃伅
+     * 
+     * @param id 浜х嚎淇℃伅涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteBsLineInfoById(Long id)
+    {
+        return bsLineInfoMapper.deleteBsLineInfoById(id);
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/material/controller/BsMaterialInfoController.java b/jcdm-main/src/main/java/com/jcdm/main/bs/material/controller/BsMaterialInfoController.java
new file mode 100644
index 0000000..efec000
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/material/controller/BsMaterialInfoController.java
@@ -0,0 +1,111 @@
+package com.jcdm.main.bs.material.controller;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.jcdm.common.utils.DateUtils;
+import com.jcdm.main.bs.material.domain.BsMaterialInfo;
+import com.jcdm.main.bs.material.service.IBsMaterialInfoService;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.common.utils.poi.ExcelUtil;
+import com.jcdm.common.core.page.TableDataInfo;
+import com.jcdm.common.utils.DateUtils;
+
+/**
+ * 鐗╂枡淇℃伅Controller
+ * 
+ * @author yyt
+ * @date 2023-12-09
+ */
+@RestController
+@RequestMapping("/bs/material")
+public class BsMaterialInfoController extends BaseController
+{
+    @Autowired
+    private IBsMaterialInfoService bsMaterialInfoService;
+
+    /**
+     * 鏌ヨ鐗╂枡淇℃伅鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('bs:material:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(BsMaterialInfo bsMaterialInfo)
+    {
+        startPage();
+        List<BsMaterialInfo> list = bsMaterialInfoService.selectBsMaterialInfoList(bsMaterialInfo);
+        return getDataTable(list);
+    }
+
+    /**
+     * 瀵煎嚭鐗╂枡淇℃伅鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('bs:material:export')")
+    @Log(title = "鐗╂枡淇℃伅", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, BsMaterialInfo bsMaterialInfo)
+    {
+        List<BsMaterialInfo> list = bsMaterialInfoService.selectBsMaterialInfoList(bsMaterialInfo);
+        ExcelUtil<BsMaterialInfo> util = new ExcelUtil<BsMaterialInfo>(BsMaterialInfo.class);
+        util.exportExcel(response, list, "鐗╂枡淇℃伅鏁版嵁");
+    }
+
+    /**
+     * 鑾峰彇鐗╂枡淇℃伅璇︾粏淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('bs:material:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(bsMaterialInfoService.selectBsMaterialInfoById(id));
+    }
+
+    /**
+     * 鏂板鐗╂枡淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('bs:material:add')")
+    @Log(title = "鐗╂枡淇℃伅", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody BsMaterialInfo bsMaterialInfo)
+    {
+        bsMaterialInfo.setCreateBy(getUsername());
+        bsMaterialInfo.setCreateTime(DateUtils.getNowDate());
+        return toAjax(bsMaterialInfoService.insertBsMaterialInfo(bsMaterialInfo));
+    }
+
+    /**
+     * 淇敼鐗╂枡淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('bs:material:edit')")
+    @Log(title = "鐗╂枡淇℃伅", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody BsMaterialInfo bsMaterialInfo)
+    {
+        bsMaterialInfo.setUpdateBy(getUsername());
+        bsMaterialInfo.setUpdateTime(DateUtils.getNowDate());
+        return toAjax(bsMaterialInfoService.updateBsMaterialInfo(bsMaterialInfo));
+    }
+
+    /**
+     * 鍒犻櫎鐗╂枡淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('bs:material:remove')")
+    @Log(title = "鐗╂枡淇℃伅", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(bsMaterialInfoService.deleteBsMaterialInfoByIds(ids));
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/material/domain/BsMaterialInfo.java b/jcdm-main/src/main/java/com/jcdm/main/bs/material/domain/BsMaterialInfo.java
new file mode 100644
index 0000000..0885f59
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/material/domain/BsMaterialInfo.java
@@ -0,0 +1,249 @@
+package com.jcdm.main.bs.material.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.core.domain.BaseEntity;
+
+/**
+ * 鐗╂枡淇℃伅瀵硅薄 bs_material_info
+ * 
+ * @author yyt
+ * @date 2023-12-09
+ */
+public class BsMaterialInfo extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 涓婚敭id */
+    private Long id;
+
+    /** 鐗╂枡缂栧彿 */
+    @Excel(name = "鐗╂枡缂栧彿")
+    private String materialCode;
+
+    /** 鐗╂枡鍚嶇О */
+    @Excel(name = "鐗╂枡鍚嶇О")
+    private String materialName;
+
+    /** 瑙嗗浘 */
+    @Excel(name = "瑙嗗浘")
+    private String materialView;
+
+    /** 绉嶇被 */
+    @Excel(name = "绉嶇被")
+    private String typeZ;
+
+    /** 绫诲瀷 */
+    @Excel(name = "绫诲瀷")
+    private String typeL;
+
+    /** 鍗曚綅 */
+    @Excel(name = "鍗曚綅")
+    private String unit;
+
+    /** 鐗堟湰 */
+    @Excel(name = "鐗堟湰")
+    private String matterVersion;
+
+    /** 澶囨敞 */
+    @Excel(name = "澶囨敞")
+    private String remarks;
+
+    /** 鍒涘缓鐢ㄦ埛 */
+    @Excel(name = "鍒涘缓鐢ㄦ埛")
+    private String createUser;
+
+    /** 鏇存敼鐢ㄦ埛 */
+    @Excel(name = "鏇存敼鐢ㄦ埛")
+    private String updateUser;
+
+    /** ERP瑙勬牸 */
+    @Excel(name = "ERP瑙勬牸")
+    private String erpSpec;
+
+    /** 鏁版嵁鏉ユ簮 */
+    @Excel(name = "鏁版嵁鏉ユ簮")
+    private String dataSource;
+
+    /** 鐗堟湰 */
+    @Excel(name = "鐗堟湰")
+    private String version;
+
+    /** 鐘舵�� */
+    @Excel(name = "鐘舵��")
+    private String status;
+
+    /** 鍘傚晢 */
+    @Excel(name = "鍘傚晢")
+    private String supplier;
+
+    public void setId(Long id) 
+    {
+        this.id = id;
+    }
+
+    public Long getId() 
+    {
+        return id;
+    }
+    public void setMaterialCode(String materialCode) 
+    {
+        this.materialCode = materialCode;
+    }
+
+    public String getMaterialCode() 
+    {
+        return materialCode;
+    }
+    public void setMaterialName(String materialName) 
+    {
+        this.materialName = materialName;
+    }
+
+    public String getMaterialName() 
+    {
+        return materialName;
+    }
+    public void setMaterialView(String materialView) 
+    {
+        this.materialView = materialView;
+    }
+
+    public String getMaterialView() 
+    {
+        return materialView;
+    }
+    public void setTypeZ(String typeZ) 
+    {
+        this.typeZ = typeZ;
+    }
+
+    public String getTypeZ() 
+    {
+        return typeZ;
+    }
+    public void setTypeL(String typeL) 
+    {
+        this.typeL = typeL;
+    }
+
+    public String getTypeL() 
+    {
+        return typeL;
+    }
+    public void setUnit(String unit) 
+    {
+        this.unit = unit;
+    }
+
+    public String getUnit() 
+    {
+        return unit;
+    }
+    public void setMatterVersion(String matterVersion) 
+    {
+        this.matterVersion = matterVersion;
+    }
+
+    public String getMatterVersion() 
+    {
+        return matterVersion;
+    }
+    public void setRemarks(String remarks) 
+    {
+        this.remarks = remarks;
+    }
+
+    public String getRemarks() 
+    {
+        return remarks;
+    }
+    public void setCreateUser(String createUser) 
+    {
+        this.createUser = createUser;
+    }
+
+    public String getCreateUser() 
+    {
+        return createUser;
+    }
+    public void setUpdateUser(String updateUser) 
+    {
+        this.updateUser = updateUser;
+    }
+
+    public String getUpdateUser() 
+    {
+        return updateUser;
+    }
+    public void setErpSpec(String erpSpec) 
+    {
+        this.erpSpec = erpSpec;
+    }
+
+    public String getErpSpec() 
+    {
+        return erpSpec;
+    }
+    public void setDataSource(String dataSource) 
+    {
+        this.dataSource = dataSource;
+    }
+
+    public String getDataSource() 
+    {
+        return dataSource;
+    }
+    public void setVersion(String version) 
+    {
+        this.version = version;
+    }
+
+    public String getVersion() 
+    {
+        return version;
+    }
+    public void setStatus(String status) 
+    {
+        this.status = status;
+    }
+
+    public String getStatus() 
+    {
+        return status;
+    }
+    public void setSupplier(String supplier) 
+    {
+        this.supplier = supplier;
+    }
+
+    public String getSupplier() 
+    {
+        return supplier;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("materialCode", getMaterialCode())
+            .append("materialName", getMaterialName())
+            .append("materialView", getMaterialView())
+            .append("typeZ", getTypeZ())
+            .append("typeL", getTypeL())
+            .append("unit", getUnit())
+            .append("matterVersion", getMatterVersion())
+            .append("remarks", getRemarks())
+            .append("createUser", getCreateUser())
+            .append("createTime", getCreateTime())
+            .append("updateUser", getUpdateUser())
+            .append("updateTime", getUpdateTime())
+            .append("erpSpec", getErpSpec())
+            .append("dataSource", getDataSource())
+            .append("version", getVersion())
+            .append("status", getStatus())
+            .append("supplier", getSupplier())
+            .toString();
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/material/mapper/BsMaterialInfoMapper.java b/jcdm-main/src/main/java/com/jcdm/main/bs/material/mapper/BsMaterialInfoMapper.java
new file mode 100644
index 0000000..7f38b9d
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/material/mapper/BsMaterialInfoMapper.java
@@ -0,0 +1,62 @@
+package com.jcdm.main.bs.material.mapper;
+
+import com.jcdm.main.bs.material.domain.BsMaterialInfo;
+
+import java.util.List;
+
+/**
+ * 鐗╂枡淇℃伅Mapper鎺ュ彛
+ * 
+ * @author yyt
+ * @date 2023-12-09
+ */
+public interface BsMaterialInfoMapper
+{
+    /**
+     * 鏌ヨ鐗╂枡淇℃伅
+     * 
+     * @param id 鐗╂枡淇℃伅涓婚敭
+     * @return 鐗╂枡淇℃伅
+     */
+    public BsMaterialInfo selectBsMaterialInfoById(Long id);
+
+    /**
+     * 鏌ヨ鐗╂枡淇℃伅鍒楄〃
+     * 
+     * @param bsMaterialInfo 鐗╂枡淇℃伅
+     * @return 鐗╂枡淇℃伅闆嗗悎
+     */
+    public List<BsMaterialInfo> selectBsMaterialInfoList(BsMaterialInfo bsMaterialInfo);
+
+    /**
+     * 鏂板鐗╂枡淇℃伅
+     * 
+     * @param bsMaterialInfo 鐗╂枡淇℃伅
+     * @return 缁撴灉
+     */
+    public int insertBsMaterialInfo(BsMaterialInfo bsMaterialInfo);
+
+    /**
+     * 淇敼鐗╂枡淇℃伅
+     * 
+     * @param bsMaterialInfo 鐗╂枡淇℃伅
+     * @return 缁撴灉
+     */
+    public int updateBsMaterialInfo(BsMaterialInfo bsMaterialInfo);
+
+    /**
+     * 鍒犻櫎鐗╂枡淇℃伅
+     * 
+     * @param id 鐗╂枡淇℃伅涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteBsMaterialInfoById(Long id);
+
+    /**
+     * 鎵归噺鍒犻櫎鐗╂枡淇℃伅
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteBsMaterialInfoByIds(Long[] ids);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/material/service/IBsMaterialInfoService.java b/jcdm-main/src/main/java/com/jcdm/main/bs/material/service/IBsMaterialInfoService.java
new file mode 100644
index 0000000..33f18f0
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/material/service/IBsMaterialInfoService.java
@@ -0,0 +1,62 @@
+package com.jcdm.main.bs.material.service;
+
+import com.jcdm.main.bs.material.domain.BsMaterialInfo;
+
+import java.util.List;
+
+/**
+ * 鐗╂枡淇℃伅Service鎺ュ彛
+ * 
+ * @author yyt
+ * @date 2023-12-09
+ */
+public interface IBsMaterialInfoService 
+{
+    /**
+     * 鏌ヨ鐗╂枡淇℃伅
+     * 
+     * @param id 鐗╂枡淇℃伅涓婚敭
+     * @return 鐗╂枡淇℃伅
+     */
+    public BsMaterialInfo selectBsMaterialInfoById(Long id);
+
+    /**
+     * 鏌ヨ鐗╂枡淇℃伅鍒楄〃
+     * 
+     * @param bsMaterialInfo 鐗╂枡淇℃伅
+     * @return 鐗╂枡淇℃伅闆嗗悎
+     */
+    public List<BsMaterialInfo> selectBsMaterialInfoList(BsMaterialInfo bsMaterialInfo);
+
+    /**
+     * 鏂板鐗╂枡淇℃伅
+     * 
+     * @param bsMaterialInfo 鐗╂枡淇℃伅
+     * @return 缁撴灉
+     */
+    public int insertBsMaterialInfo(BsMaterialInfo bsMaterialInfo);
+
+    /**
+     * 淇敼鐗╂枡淇℃伅
+     * 
+     * @param bsMaterialInfo 鐗╂枡淇℃伅
+     * @return 缁撴灉
+     */
+    public int updateBsMaterialInfo(BsMaterialInfo bsMaterialInfo);
+
+    /**
+     * 鎵归噺鍒犻櫎鐗╂枡淇℃伅
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鐗╂枡淇℃伅涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteBsMaterialInfoByIds(Long[] ids);
+
+    /**
+     * 鍒犻櫎鐗╂枡淇℃伅淇℃伅
+     * 
+     * @param id 鐗╂枡淇℃伅涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteBsMaterialInfoById(Long id);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/material/service/impl/BsMaterialInfoServiceImpl.java b/jcdm-main/src/main/java/com/jcdm/main/bs/material/service/impl/BsMaterialInfoServiceImpl.java
new file mode 100644
index 0000000..bd47eef
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/material/service/impl/BsMaterialInfoServiceImpl.java
@@ -0,0 +1,94 @@
+package com.jcdm.main.bs.material.service.impl;
+
+import java.util.List;
+import com.jcdm.common.utils.DateUtils;
+import com.jcdm.main.bs.material.domain.BsMaterialInfo;
+import com.jcdm.main.bs.material.mapper.BsMaterialInfoMapper;
+import com.jcdm.main.bs.material.service.IBsMaterialInfoService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * 鐗╂枡淇℃伅Service涓氬姟灞傚鐞�
+ * 
+ * @author yyt
+ * @date 2023-12-09
+ */
+@Service
+public class BsMaterialInfoServiceImpl implements IBsMaterialInfoService
+{
+    @Autowired
+    private BsMaterialInfoMapper bsMaterialInfoMapper;
+
+    /**
+     * 鏌ヨ鐗╂枡淇℃伅
+     * 
+     * @param id 鐗╂枡淇℃伅涓婚敭
+     * @return 鐗╂枡淇℃伅
+     */
+    @Override
+    public BsMaterialInfo selectBsMaterialInfoById(Long id)
+    {
+        return bsMaterialInfoMapper.selectBsMaterialInfoById(id);
+    }
+
+    /**
+     * 鏌ヨ鐗╂枡淇℃伅鍒楄〃
+     * 
+     * @param bsMaterialInfo 鐗╂枡淇℃伅
+     * @return 鐗╂枡淇℃伅
+     */
+    @Override
+    public List<BsMaterialInfo> selectBsMaterialInfoList(BsMaterialInfo bsMaterialInfo)
+    {
+        return bsMaterialInfoMapper.selectBsMaterialInfoList(bsMaterialInfo);
+    }
+
+    /**
+     * 鏂板鐗╂枡淇℃伅
+     * 
+     * @param bsMaterialInfo 鐗╂枡淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertBsMaterialInfo(BsMaterialInfo bsMaterialInfo)
+    {
+        return bsMaterialInfoMapper.insertBsMaterialInfo(bsMaterialInfo);
+    }
+
+    /**
+     * 淇敼鐗╂枡淇℃伅
+     * 
+     * @param bsMaterialInfo 鐗╂枡淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateBsMaterialInfo(BsMaterialInfo bsMaterialInfo)
+    {
+        return bsMaterialInfoMapper.updateBsMaterialInfo(bsMaterialInfo);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎鐗╂枡淇℃伅
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鐗╂枡淇℃伅涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteBsMaterialInfoByIds(Long[] ids)
+    {
+        return bsMaterialInfoMapper.deleteBsMaterialInfoByIds(ids);
+    }
+
+    /**
+     * 鍒犻櫎鐗╂枡淇℃伅淇℃伅
+     * 
+     * @param id 鐗╂枡淇℃伅涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteBsMaterialInfoById(Long id)
+    {
+        return bsMaterialInfoMapper.deleteBsMaterialInfoById(id);
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/processFile/controller/BsProcessFileController.java b/jcdm-main/src/main/java/com/jcdm/main/bs/processFile/controller/BsProcessFileController.java
new file mode 100644
index 0000000..8dac115
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/processFile/controller/BsProcessFileController.java
@@ -0,0 +1,104 @@
+package com.jcdm.main.bs.processFile.controller;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.main.bs.processFile.domain.BsProcessFile;
+import com.jcdm.main.bs.processFile.service.IBsProcessFileService;
+import com.jcdm.common.utils.poi.ExcelUtil;
+import com.jcdm.common.core.page.TableDataInfo;
+
+/**
+ * 宸ヨ壓鏂囨。Controller
+ * 
+ * @author Yi
+ * @date 2024-01-03
+ */
+@RestController
+@RequestMapping("/bs/processFile")
+public class BsProcessFileController extends BaseController
+{
+    @Autowired
+    private IBsProcessFileService bsProcessFileService;
+
+    /**
+     * 鏌ヨ宸ヨ壓鏂囨。鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('bs:processFile:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(BsProcessFile bsProcessFile)
+    {
+        startPage();
+        List<BsProcessFile> list = bsProcessFileService.selectBsProcessFileList(bsProcessFile);
+        return getDataTable(list);
+    }
+
+    /**
+     * 瀵煎嚭宸ヨ壓鏂囨。鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('bs:processFile:export')")
+    @Log(title = "宸ヨ壓鏂囨。", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, BsProcessFile bsProcessFile)
+    {
+        List<BsProcessFile> list = bsProcessFileService.selectBsProcessFileList(bsProcessFile);
+        ExcelUtil<BsProcessFile> util = new ExcelUtil<BsProcessFile>(BsProcessFile.class);
+        util.exportExcel(response, list, "宸ヨ壓鏂囨。鏁版嵁");
+    }
+
+    /**
+     * 鑾峰彇宸ヨ壓鏂囨。璇︾粏淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('bs:processFile:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(bsProcessFileService.selectBsProcessFileById(id));
+    }
+
+    /**
+     * 鏂板宸ヨ壓鏂囨。
+     */
+    @PreAuthorize("@ss.hasPermi('bs:processFile:add')")
+    @Log(title = "宸ヨ壓鏂囨。", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody BsProcessFile bsProcessFile)
+    {
+        return toAjax(bsProcessFileService.insertBsProcessFile(bsProcessFile));
+    }
+
+    /**
+     * 淇敼宸ヨ壓鏂囨。
+     */
+    @PreAuthorize("@ss.hasPermi('bs:processFile:edit')")
+    @Log(title = "宸ヨ壓鏂囨。", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody BsProcessFile bsProcessFile)
+    {
+        return toAjax(bsProcessFileService.updateBsProcessFile(bsProcessFile));
+    }
+
+    /**
+     * 鍒犻櫎宸ヨ壓鏂囨。
+     */
+    @PreAuthorize("@ss.hasPermi('bs:processFile:remove')")
+    @Log(title = "宸ヨ壓鏂囨。", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(bsProcessFileService.deleteBsProcessFileByIds(ids));
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/processFile/domain/BsProcessFile.java b/jcdm-main/src/main/java/com/jcdm/main/bs/processFile/domain/BsProcessFile.java
new file mode 100644
index 0000000..1c65568
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/processFile/domain/BsProcessFile.java
@@ -0,0 +1,245 @@
+package com.jcdm.main.bs.processFile.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.core.domain.BaseEntity;
+
+/**
+ * 宸ヨ壓鏂囨。瀵硅薄 bs_process_file
+ * 
+ * @author Yi
+ * @date 2024-01-03
+ */
+public class BsProcessFile extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** id */
+    private Long id;
+
+    /** 浜у搧缂栧彿 */
+    @Excel(name = "浜у搧缂栧彿")
+    private String productCode;
+
+    /** 浜у搧鍚嶇О */
+    @Excel(name = "浜у搧鍚嶇О")
+    private String productName;
+
+    /** 宸ュ簭缂栧彿 */
+    @Excel(name = "宸ュ簭缂栧彿")
+    private String processesCode;
+
+    /** 宸ュ簭鍚嶇О */
+    @Excel(name = "宸ュ簭鍚嶇О")
+    private String processesName;
+
+    /** 鏂囦欢缂栧彿 */
+    @Excel(name = "鏂囦欢缂栧彿")
+    private String fileCode;
+
+    /** 鏂囦欢鍚嶇О */
+    @Excel(name = "鏂囦欢鍚嶇О")
+    private String fileName;
+
+    /** 鏂囦欢鍦板潃 */
+    @Excel(name = "鏂囦欢鍦板潃")
+    private String fileAddress;
+
+    /** 鐘舵�� */
+    @Excel(name = "鐘舵��")
+    private String status;
+
+    /** 鍒涘缓浜� */
+    @Excel(name = "鍒涘缓浜�")
+    private String createUser;
+
+    /** 鏇存柊浜� */
+    @Excel(name = "鏇存柊浜�")
+    private String updateUser;
+
+    /** 棰勭暀瀛楁1 */
+    private String spareField1;
+
+    /** 棰勭暀瀛楁2 */
+    private String spareField2;
+
+    /** 棰勭暀瀛楁3 */
+    private String spareField3;
+
+    /** 棰勭暀瀛楁4 */
+    private String spareField4;
+
+    /** 澶囨敞 */
+    @Excel(name = "澶囨敞")
+    private String remarks;
+
+    public void setId(Long id) 
+    {
+        this.id = id;
+    }
+
+    public Long getId() 
+    {
+        return id;
+    }
+    public void setProductCode(String productCode) 
+    {
+        this.productCode = productCode;
+    }
+
+    public String getProductCode() 
+    {
+        return productCode;
+    }
+    public void setProductName(String productName) 
+    {
+        this.productName = productName;
+    }
+
+    public String getProductName() 
+    {
+        return productName;
+    }
+    public void setProcessesCode(String processesCode) 
+    {
+        this.processesCode = processesCode;
+    }
+
+    public String getProcessesCode() 
+    {
+        return processesCode;
+    }
+    public void setProcessesName(String processesName) 
+    {
+        this.processesName = processesName;
+    }
+
+    public String getProcessesName() 
+    {
+        return processesName;
+    }
+    public void setFileCode(String fileCode) 
+    {
+        this.fileCode = fileCode;
+    }
+
+    public String getFileCode() 
+    {
+        return fileCode;
+    }
+    public void setFileName(String fileName) 
+    {
+        this.fileName = fileName;
+    }
+
+    public String getFileName() 
+    {
+        return fileName;
+    }
+    public void setFileAddress(String fileAddress) 
+    {
+        this.fileAddress = fileAddress;
+    }
+
+    public String getFileAddress() 
+    {
+        return fileAddress;
+    }
+    public void setStatus(String status) 
+    {
+        this.status = status;
+    }
+
+    public String getStatus() 
+    {
+        return status;
+    }
+    public void setCreateUser(String createUser) 
+    {
+        this.createUser = createUser;
+    }
+
+    public String getCreateUser() 
+    {
+        return createUser;
+    }
+    public void setUpdateUser(String updateUser) 
+    {
+        this.updateUser = updateUser;
+    }
+
+    public String getUpdateUser() 
+    {
+        return updateUser;
+    }
+    public void setSpareField1(String spareField1) 
+    {
+        this.spareField1 = spareField1;
+    }
+
+    public String getSpareField1() 
+    {
+        return spareField1;
+    }
+    public void setSpareField2(String spareField2) 
+    {
+        this.spareField2 = spareField2;
+    }
+
+    public String getSpareField2() 
+    {
+        return spareField2;
+    }
+    public void setSpareField3(String spareField3) 
+    {
+        this.spareField3 = spareField3;
+    }
+
+    public String getSpareField3() 
+    {
+        return spareField3;
+    }
+    public void setSpareField4(String spareField4) 
+    {
+        this.spareField4 = spareField4;
+    }
+
+    public String getSpareField4() 
+    {
+        return spareField4;
+    }
+    public void setRemarks(String remarks) 
+    {
+        this.remarks = remarks;
+    }
+
+    public String getRemarks() 
+    {
+        return remarks;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("productCode", getProductCode())
+            .append("productName", getProductName())
+            .append("processesCode", getProcessesCode())
+            .append("processesName", getProcessesName())
+            .append("fileCode", getFileCode())
+            .append("fileName", getFileName())
+            .append("fileAddress", getFileAddress())
+            .append("status", getStatus())
+            .append("createUser", getCreateUser())
+            .append("createTime", getCreateTime())
+            .append("updateUser", getUpdateUser())
+            .append("updateTime", getUpdateTime())
+            .append("spareField1", getSpareField1())
+            .append("spareField2", getSpareField2())
+            .append("spareField3", getSpareField3())
+            .append("spareField4", getSpareField4())
+            .append("remarks", getRemarks())
+            .toString();
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/processFile/mapper/BsProcessFileMapper.java b/jcdm-main/src/main/java/com/jcdm/main/bs/processFile/mapper/BsProcessFileMapper.java
new file mode 100644
index 0000000..6db02aa
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/processFile/mapper/BsProcessFileMapper.java
@@ -0,0 +1,61 @@
+package com.jcdm.main.bs.processFile.mapper;
+
+import java.util.List;
+import com.jcdm.main.bs.processFile.domain.BsProcessFile;
+
+/**
+ * 宸ヨ壓鏂囨。Mapper鎺ュ彛
+ * 
+ * @author Yi
+ * @date 2024-01-03
+ */
+public interface BsProcessFileMapper 
+{
+    /**
+     * 鏌ヨ宸ヨ壓鏂囨。
+     * 
+     * @param id 宸ヨ壓鏂囨。涓婚敭
+     * @return 宸ヨ壓鏂囨。
+     */
+    public BsProcessFile selectBsProcessFileById(Long id);
+
+    /**
+     * 鏌ヨ宸ヨ壓鏂囨。鍒楄〃
+     * 
+     * @param bsProcessFile 宸ヨ壓鏂囨。
+     * @return 宸ヨ壓鏂囨。闆嗗悎
+     */
+    public List<BsProcessFile> selectBsProcessFileList(BsProcessFile bsProcessFile);
+
+    /**
+     * 鏂板宸ヨ壓鏂囨。
+     * 
+     * @param bsProcessFile 宸ヨ壓鏂囨。
+     * @return 缁撴灉
+     */
+    public int insertBsProcessFile(BsProcessFile bsProcessFile);
+
+    /**
+     * 淇敼宸ヨ壓鏂囨。
+     * 
+     * @param bsProcessFile 宸ヨ壓鏂囨。
+     * @return 缁撴灉
+     */
+    public int updateBsProcessFile(BsProcessFile bsProcessFile);
+
+    /**
+     * 鍒犻櫎宸ヨ壓鏂囨。
+     * 
+     * @param id 宸ヨ壓鏂囨。涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteBsProcessFileById(Long id);
+
+    /**
+     * 鎵归噺鍒犻櫎宸ヨ壓鏂囨。
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteBsProcessFileByIds(Long[] ids);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/processFile/service/IBsProcessFileService.java b/jcdm-main/src/main/java/com/jcdm/main/bs/processFile/service/IBsProcessFileService.java
new file mode 100644
index 0000000..075a8b4
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/processFile/service/IBsProcessFileService.java
@@ -0,0 +1,61 @@
+package com.jcdm.main.bs.processFile.service;
+
+import java.util.List;
+import com.jcdm.main.bs.processFile.domain.BsProcessFile;
+
+/**
+ * 宸ヨ壓鏂囨。Service鎺ュ彛
+ * 
+ * @author Yi
+ * @date 2024-01-03
+ */
+public interface IBsProcessFileService 
+{
+    /**
+     * 鏌ヨ宸ヨ壓鏂囨。
+     * 
+     * @param id 宸ヨ壓鏂囨。涓婚敭
+     * @return 宸ヨ壓鏂囨。
+     */
+    public BsProcessFile selectBsProcessFileById(Long id);
+
+    /**
+     * 鏌ヨ宸ヨ壓鏂囨。鍒楄〃
+     * 
+     * @param bsProcessFile 宸ヨ壓鏂囨。
+     * @return 宸ヨ壓鏂囨。闆嗗悎
+     */
+    public List<BsProcessFile> selectBsProcessFileList(BsProcessFile bsProcessFile);
+
+    /**
+     * 鏂板宸ヨ壓鏂囨。
+     * 
+     * @param bsProcessFile 宸ヨ壓鏂囨。
+     * @return 缁撴灉
+     */
+    public int insertBsProcessFile(BsProcessFile bsProcessFile);
+
+    /**
+     * 淇敼宸ヨ壓鏂囨。
+     * 
+     * @param bsProcessFile 宸ヨ壓鏂囨。
+     * @return 缁撴灉
+     */
+    public int updateBsProcessFile(BsProcessFile bsProcessFile);
+
+    /**
+     * 鎵归噺鍒犻櫎宸ヨ壓鏂囨。
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑宸ヨ壓鏂囨。涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteBsProcessFileByIds(Long[] ids);
+
+    /**
+     * 鍒犻櫎宸ヨ壓鏂囨。淇℃伅
+     * 
+     * @param id 宸ヨ壓鏂囨。涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteBsProcessFileById(Long id);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/processFile/service/impl/BsProcessFileServiceImpl.java b/jcdm-main/src/main/java/com/jcdm/main/bs/processFile/service/impl/BsProcessFileServiceImpl.java
new file mode 100644
index 0000000..9d05656
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/processFile/service/impl/BsProcessFileServiceImpl.java
@@ -0,0 +1,96 @@
+package com.jcdm.main.bs.processFile.service.impl;
+
+import java.util.List;
+import com.jcdm.common.utils.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.jcdm.main.bs.processFile.mapper.BsProcessFileMapper;
+import com.jcdm.main.bs.processFile.domain.BsProcessFile;
+import com.jcdm.main.bs.processFile.service.IBsProcessFileService;
+
+/**
+ * 宸ヨ壓鏂囨。Service涓氬姟灞傚鐞�
+ * 
+ * @author Yi
+ * @date 2024-01-03
+ */
+@Service
+public class BsProcessFileServiceImpl implements IBsProcessFileService 
+{
+    @Autowired
+    private BsProcessFileMapper bsProcessFileMapper;
+
+    /**
+     * 鏌ヨ宸ヨ壓鏂囨。
+     * 
+     * @param id 宸ヨ壓鏂囨。涓婚敭
+     * @return 宸ヨ壓鏂囨。
+     */
+    @Override
+    public BsProcessFile selectBsProcessFileById(Long id)
+    {
+        return bsProcessFileMapper.selectBsProcessFileById(id);
+    }
+
+    /**
+     * 鏌ヨ宸ヨ壓鏂囨。鍒楄〃
+     * 
+     * @param bsProcessFile 宸ヨ壓鏂囨。
+     * @return 宸ヨ壓鏂囨。
+     */
+    @Override
+    public List<BsProcessFile> selectBsProcessFileList(BsProcessFile bsProcessFile)
+    {
+        return bsProcessFileMapper.selectBsProcessFileList(bsProcessFile);
+    }
+
+    /**
+     * 鏂板宸ヨ壓鏂囨。
+     * 
+     * @param bsProcessFile 宸ヨ壓鏂囨。
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertBsProcessFile(BsProcessFile bsProcessFile)
+    {
+        bsProcessFile.setCreateTime(DateUtils.getNowDate());
+        return bsProcessFileMapper.insertBsProcessFile(bsProcessFile);
+    }
+
+    /**
+     * 淇敼宸ヨ壓鏂囨。
+     * 
+     * @param bsProcessFile 宸ヨ壓鏂囨。
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateBsProcessFile(BsProcessFile bsProcessFile)
+    {
+        bsProcessFile.setUpdateTime(DateUtils.getNowDate());
+        return bsProcessFileMapper.updateBsProcessFile(bsProcessFile);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎宸ヨ壓鏂囨。
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑宸ヨ壓鏂囨。涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteBsProcessFileByIds(Long[] ids)
+    {
+        return bsProcessFileMapper.deleteBsProcessFileByIds(ids);
+    }
+
+    /**
+     * 鍒犻櫎宸ヨ壓鏂囨。淇℃伅
+     * 
+     * @param id 宸ヨ壓鏂囨。涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteBsProcessFileById(Long id)
+    {
+        return bsProcessFileMapper.deleteBsProcessFileById(id);
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/processes/controller/BsProcessesInfoController.java b/jcdm-main/src/main/java/com/jcdm/main/bs/processes/controller/BsProcessesInfoController.java
new file mode 100644
index 0000000..19dfebd
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/processes/controller/BsProcessesInfoController.java
@@ -0,0 +1,105 @@
+package com.jcdm.main.bs.processes.controller;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.jcdm.main.bs.processes.domain.BsProcessesInfo;
+import com.jcdm.main.bs.processes.service.IBsProcessesInfoService;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.common.utils.poi.ExcelUtil;
+import com.jcdm.common.core.page.TableDataInfo;
+
+/**
+ * 宸ュ簭淇℃伅Controller
+ * 
+ * @author ruimin
+ * @date 2023-12-09
+ */
+@RestController
+@RequestMapping("/bs/processes")
+public class BsProcessesInfoController extends BaseController
+{
+    @Autowired
+    private IBsProcessesInfoService bsProcessesInfoService;
+
+    /**
+     * 鏌ヨ宸ュ簭淇℃伅鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('bs:processes:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(BsProcessesInfo bsProcessesInfo)
+    {
+        startPage();
+        List<BsProcessesInfo> list = bsProcessesInfoService.selectBsProcessesInfoList(bsProcessesInfo);
+        return getDataTable(list);
+    }
+
+    /**
+     * 瀵煎嚭宸ュ簭淇℃伅鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('bs:processes:export')")
+    @Log(title = "宸ュ簭淇℃伅", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, BsProcessesInfo bsProcessesInfo)
+    {
+        List<BsProcessesInfo> list = bsProcessesInfoService.selectBsProcessesInfoList(bsProcessesInfo);
+        ExcelUtil<BsProcessesInfo> util = new ExcelUtil<BsProcessesInfo>(BsProcessesInfo.class);
+        util.exportExcel(response, list, "宸ュ簭淇℃伅鏁版嵁");
+    }
+
+    /**
+     * 鑾峰彇宸ュ簭淇℃伅璇︾粏淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('bs:processes:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(bsProcessesInfoService.selectBsProcessesInfoById(id));
+    }
+
+    /**
+     * 鏂板宸ュ簭淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('bs:processes:add')")
+    @Log(title = "宸ュ簭淇℃伅", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody BsProcessesInfo bsProcessesInfo)
+    {
+        return toAjax(bsProcessesInfoService.insertBsProcessesInfo(bsProcessesInfo));
+    }
+
+    /**
+     * 淇敼宸ュ簭淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('bs:processes:edit')")
+    @Log(title = "宸ュ簭淇℃伅", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody BsProcessesInfo bsProcessesInfo)
+    {
+        return toAjax(bsProcessesInfoService.updateBsProcessesInfo(bsProcessesInfo));
+    }
+
+    /**
+     * 鍒犻櫎宸ュ簭淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('bs:processes:remove')")
+    @Log(title = "宸ュ簭淇℃伅", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(bsProcessesInfoService.deleteBsProcessesInfoByIds(ids));
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/processes/domain/BsProcessesInfo.java b/jcdm-main/src/main/java/com/jcdm/main/bs/processes/domain/BsProcessesInfo.java
new file mode 100644
index 0000000..7b27cc9
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/processes/domain/BsProcessesInfo.java
@@ -0,0 +1,217 @@
+package com.jcdm.main.bs.processes.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.core.domain.BaseEntity;
+
+/**
+ * 宸ュ簭淇℃伅瀵硅薄 bs_processes_info
+ * 
+ * @author ruimin
+ * @date 2023-12-09
+ */
+public class BsProcessesInfo extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 涓婚敭id */
+    private Long id;
+
+    /** 宸ュ簭缂栧彿 */
+    @Excel(name = "宸ュ簭缂栧彿")
+    private String processesCode;
+
+    /** 宸ュ簭鍚嶇О */
+    @Excel(name = "宸ュ簭鍚嶇О")
+    private String processesName;
+
+    /** 宸ュ簭绫诲瀷 */
+    @Excel(name = "宸ュ簭绫诲瀷")
+    private String processesType;
+
+    /** 鍑嗗鏃堕棿 */
+    @Excel(name = "鍑嗗鏃堕棿")
+    private String preparationTime;
+
+    /** 鐢熶骇鏃堕棿 */
+    @Excel(name = "鐢熶骇鏃堕棿")
+    private String productiveTime;
+
+    /** 鐘舵�� */
+    @Excel(name = "鐘舵��")
+    private String status;
+
+    /** 棰勭暀瀛楁1 */
+    private String spareField1;
+
+    /** 棰勭暀瀛楁2 */
+    private String spareField2;
+
+    /** 棰勭暀瀛楁3 */
+    private String spareField3;
+
+    /** 棰勭暀瀛楁4 */
+    private String spareField4;
+
+    /** 鍒涘缓鐢ㄦ埛 */
+    @Excel(name = "鍒涘缓鐢ㄦ埛")
+    private String createUser;
+
+    /** 鏇存敼鐢ㄦ埛 */
+    @Excel(name = "鏇存敼鐢ㄦ埛")
+    private String updateUser;
+
+    /** 澶囨敞 */
+    @Excel(name = "澶囨敞")
+    private String remarks;
+
+    public void setId(Long id) 
+    {
+        this.id = id;
+    }
+
+    public Long getId() 
+    {
+        return id;
+    }
+    public void setProcessesCode(String processesCode) 
+    {
+        this.processesCode = processesCode;
+    }
+
+    public String getProcessesCode() 
+    {
+        return processesCode;
+    }
+    public void setProcessesName(String processesName) 
+    {
+        this.processesName = processesName;
+    }
+
+    public String getProcessesName() 
+    {
+        return processesName;
+    }
+    public void setProcessesType(String processesType) 
+    {
+        this.processesType = processesType;
+    }
+
+    public String getProcessesType() 
+    {
+        return processesType;
+    }
+    public void setPreparationTime(String preparationTime) 
+    {
+        this.preparationTime = preparationTime;
+    }
+
+    public String getPreparationTime() 
+    {
+        return preparationTime;
+    }
+    public void setProductiveTime(String productiveTime) 
+    {
+        this.productiveTime = productiveTime;
+    }
+
+    public String getProductiveTime() 
+    {
+        return productiveTime;
+    }
+    public void setStatus(String status) 
+    {
+        this.status = status;
+    }
+
+    public String getStatus() 
+    {
+        return status;
+    }
+    public void setSpareField1(String spareField1) 
+    {
+        this.spareField1 = spareField1;
+    }
+
+    public String getSpareField1() 
+    {
+        return spareField1;
+    }
+    public void setSpareField2(String spareField2) 
+    {
+        this.spareField2 = spareField2;
+    }
+
+    public String getSpareField2() 
+    {
+        return spareField2;
+    }
+    public void setSpareField3(String spareField3) 
+    {
+        this.spareField3 = spareField3;
+    }
+
+    public String getSpareField3() 
+    {
+        return spareField3;
+    }
+    public void setSpareField4(String spareField4) 
+    {
+        this.spareField4 = spareField4;
+    }
+
+    public String getSpareField4() 
+    {
+        return spareField4;
+    }
+    public void setCreateUser(String createUser) 
+    {
+        this.createUser = createUser;
+    }
+
+    public String getCreateUser() 
+    {
+        return createUser;
+    }
+    public void setUpdateUser(String updateUser) 
+    {
+        this.updateUser = updateUser;
+    }
+
+    public String getUpdateUser() 
+    {
+        return updateUser;
+    }
+    public void setRemarks(String remarks) 
+    {
+        this.remarks = remarks;
+    }
+
+    public String getRemarks() 
+    {
+        return remarks;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("processesCode", getProcessesCode())
+            .append("processesName", getProcessesName())
+            .append("processesType", getProcessesType())
+            .append("preparationTime", getPreparationTime())
+            .append("productiveTime", getProductiveTime())
+            .append("status", getStatus())
+            .append("spareField1", getSpareField1())
+            .append("spareField2", getSpareField2())
+            .append("spareField3", getSpareField3())
+            .append("spareField4", getSpareField4())
+            .append("createUser", getCreateUser())
+            .append("createTime", getCreateTime())
+            .append("updateUser", getUpdateUser())
+            .append("updateTime", getUpdateTime())
+            .append("remarks", getRemarks())
+            .toString();
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/processes/mapper/BsProcessesInfoMapper.java b/jcdm-main/src/main/java/com/jcdm/main/bs/processes/mapper/BsProcessesInfoMapper.java
new file mode 100644
index 0000000..a0161a6
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/processes/mapper/BsProcessesInfoMapper.java
@@ -0,0 +1,62 @@
+package com.jcdm.main.bs.processes.mapper;
+
+import com.jcdm.main.bs.processes.domain.BsProcessesInfo;
+
+import java.util.List;
+
+/**
+ * 宸ュ簭淇℃伅Mapper鎺ュ彛
+ * 
+ * @author ruimin
+ * @date 2023-12-09
+ */
+public interface BsProcessesInfoMapper 
+{
+    /**
+     * 鏌ヨ宸ュ簭淇℃伅
+     * 
+     * @param id 宸ュ簭淇℃伅涓婚敭
+     * @return 宸ュ簭淇℃伅
+     */
+    public BsProcessesInfo selectBsProcessesInfoById(Long id);
+
+    /**
+     * 鏌ヨ宸ュ簭淇℃伅鍒楄〃
+     * 
+     * @param bsProcessesInfo 宸ュ簭淇℃伅
+     * @return 宸ュ簭淇℃伅闆嗗悎
+     */
+    public List<BsProcessesInfo> selectBsProcessesInfoList(BsProcessesInfo bsProcessesInfo);
+
+    /**
+     * 鏂板宸ュ簭淇℃伅
+     * 
+     * @param bsProcessesInfo 宸ュ簭淇℃伅
+     * @return 缁撴灉
+     */
+    public int insertBsProcessesInfo(BsProcessesInfo bsProcessesInfo);
+
+    /**
+     * 淇敼宸ュ簭淇℃伅
+     * 
+     * @param bsProcessesInfo 宸ュ簭淇℃伅
+     * @return 缁撴灉
+     */
+    public int updateBsProcessesInfo(BsProcessesInfo bsProcessesInfo);
+
+    /**
+     * 鍒犻櫎宸ュ簭淇℃伅
+     * 
+     * @param id 宸ュ簭淇℃伅涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteBsProcessesInfoById(Long id);
+
+    /**
+     * 鎵归噺鍒犻櫎宸ュ簭淇℃伅
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteBsProcessesInfoByIds(Long[] ids);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/processes/service/IBsProcessesInfoService.java b/jcdm-main/src/main/java/com/jcdm/main/bs/processes/service/IBsProcessesInfoService.java
new file mode 100644
index 0000000..c515f80
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/processes/service/IBsProcessesInfoService.java
@@ -0,0 +1,62 @@
+package com.jcdm.main.bs.processes.service;
+
+import com.jcdm.main.bs.processes.domain.BsProcessesInfo;
+
+import java.util.List;
+
+/**
+ * 宸ュ簭淇℃伅Service鎺ュ彛
+ * 
+ * @author ruimin
+ * @date 2023-12-09
+ */
+public interface IBsProcessesInfoService 
+{
+    /**
+     * 鏌ヨ宸ュ簭淇℃伅
+     * 
+     * @param id 宸ュ簭淇℃伅涓婚敭
+     * @return 宸ュ簭淇℃伅
+     */
+    public BsProcessesInfo selectBsProcessesInfoById(Long id);
+
+    /**
+     * 鏌ヨ宸ュ簭淇℃伅鍒楄〃
+     * 
+     * @param bsProcessesInfo 宸ュ簭淇℃伅
+     * @return 宸ュ簭淇℃伅闆嗗悎
+     */
+    public List<BsProcessesInfo> selectBsProcessesInfoList(BsProcessesInfo bsProcessesInfo);
+
+    /**
+     * 鏂板宸ュ簭淇℃伅
+     * 
+     * @param bsProcessesInfo 宸ュ簭淇℃伅
+     * @return 缁撴灉
+     */
+    public int insertBsProcessesInfo(BsProcessesInfo bsProcessesInfo);
+
+    /**
+     * 淇敼宸ュ簭淇℃伅
+     * 
+     * @param bsProcessesInfo 宸ュ簭淇℃伅
+     * @return 缁撴灉
+     */
+    public int updateBsProcessesInfo(BsProcessesInfo bsProcessesInfo);
+
+    /**
+     * 鎵归噺鍒犻櫎宸ュ簭淇℃伅
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑宸ュ簭淇℃伅涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteBsProcessesInfoByIds(Long[] ids);
+
+    /**
+     * 鍒犻櫎宸ュ簭淇℃伅淇℃伅
+     * 
+     * @param id 宸ュ簭淇℃伅涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteBsProcessesInfoById(Long id);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/processes/service/impl/BsProcessesInfoServiceImpl.java b/jcdm-main/src/main/java/com/jcdm/main/bs/processes/service/impl/BsProcessesInfoServiceImpl.java
new file mode 100644
index 0000000..93b083b
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/processes/service/impl/BsProcessesInfoServiceImpl.java
@@ -0,0 +1,100 @@
+package com.jcdm.main.bs.processes.service.impl;
+
+import java.util.List;
+import com.jcdm.common.utils.DateUtils;
+import com.jcdm.main.bs.processes.domain.BsProcessesInfo;
+import com.jcdm.main.bs.processes.mapper.BsProcessesInfoMapper;
+import com.jcdm.main.bs.processes.service.IBsProcessesInfoService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import static org.apache.commons.lang3.SystemUtils.getUserName;
+
+/**
+ * 宸ュ簭淇℃伅Service涓氬姟灞傚鐞�
+ * 
+ * @author ruimin
+ * @date 2023-12-09
+ */
+@Service
+public class BsProcessesInfoServiceImpl implements IBsProcessesInfoService
+{
+    @Autowired
+    private BsProcessesInfoMapper bsProcessesInfoMapper;
+
+    /**
+     * 鏌ヨ宸ュ簭淇℃伅
+     * 
+     * @param id 宸ュ簭淇℃伅涓婚敭
+     * @return 宸ュ簭淇℃伅
+     */
+    @Override
+    public BsProcessesInfo selectBsProcessesInfoById(Long id)
+    {
+        return bsProcessesInfoMapper.selectBsProcessesInfoById(id);
+    }
+
+    /**
+     * 鏌ヨ宸ュ簭淇℃伅鍒楄〃
+     * 
+     * @param bsProcessesInfo 宸ュ簭淇℃伅
+     * @return 宸ュ簭淇℃伅
+     */
+    @Override
+    public List<BsProcessesInfo> selectBsProcessesInfoList(BsProcessesInfo bsProcessesInfo)
+    {
+        return bsProcessesInfoMapper.selectBsProcessesInfoList(bsProcessesInfo);
+    }
+
+    /**
+     * 鏂板宸ュ簭淇℃伅
+     * 
+     * @param bsProcessesInfo 宸ュ簭淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertBsProcessesInfo(BsProcessesInfo bsProcessesInfo)
+    {
+        bsProcessesInfo.setCreateTime(DateUtils.getNowDate());
+        bsProcessesInfo.setCreateUser(getUserName());
+        return bsProcessesInfoMapper.insertBsProcessesInfo(bsProcessesInfo);
+    }
+
+    /**
+     * 淇敼宸ュ簭淇℃伅
+     * 
+     * @param bsProcessesInfo 宸ュ簭淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateBsProcessesInfo(BsProcessesInfo bsProcessesInfo)
+    {
+        bsProcessesInfo.setUpdateTime(DateUtils.getNowDate());
+        bsProcessesInfo.setUpdateUser(getUserName());
+        return bsProcessesInfoMapper.updateBsProcessesInfo(bsProcessesInfo);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎宸ュ簭淇℃伅
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑宸ュ簭淇℃伅涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteBsProcessesInfoByIds(Long[] ids)
+    {
+        return bsProcessesInfoMapper.deleteBsProcessesInfoByIds(ids);
+    }
+
+    /**
+     * 鍒犻櫎宸ュ簭淇℃伅淇℃伅
+     * 
+     * @param id 宸ュ簭淇℃伅涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteBsProcessesInfoById(Long id)
+    {
+        return bsProcessesInfoMapper.deleteBsProcessesInfoById(id);
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/productBom/controller/BsProductBomInfoController.java b/jcdm-main/src/main/java/com/jcdm/main/bs/productBom/controller/BsProductBomInfoController.java
new file mode 100644
index 0000000..47f8d10
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/productBom/controller/BsProductBomInfoController.java
@@ -0,0 +1,110 @@
+package com.jcdm.main.bs.productBom.controller;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.jcdm.common.utils.DateUtils;
+import com.jcdm.main.bs.productBom.domain.BsProductBomInfo;
+import com.jcdm.main.bs.productBom.service.IBsProductBomInfoService;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.common.utils.poi.ExcelUtil;
+import com.jcdm.common.core.page.TableDataInfo;
+
+/**
+ * 鍩虹BOMController
+ * 
+ * @author yyt
+ * @date 2023-12-11
+ */
+@RestController
+@RequestMapping("/bs/ProductBom")
+public class BsProductBomInfoController extends BaseController
+{
+    @Autowired
+    private IBsProductBomInfoService bsProductBomInfoService;
+
+    /**
+     * 鏌ヨ鍩虹BOM鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('bs:ProductBom:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(BsProductBomInfo bsProductBomInfo)
+    {
+        startPage();
+        List<BsProductBomInfo> list = bsProductBomInfoService.selectBsProductBomInfoList(bsProductBomInfo);
+        return getDataTable(list);
+    }
+
+    /**
+     * 瀵煎嚭鍩虹BOM鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('bs:ProductBom:export')")
+    @Log(title = "鍩虹BOM", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, BsProductBomInfo bsProductBomInfo)
+    {
+        List<BsProductBomInfo> list = bsProductBomInfoService.selectBsProductBomInfoList(bsProductBomInfo);
+        ExcelUtil<BsProductBomInfo> util = new ExcelUtil<BsProductBomInfo>(BsProductBomInfo.class);
+        util.exportExcel(response, list, "鍩虹BOM鏁版嵁");
+    }
+
+    /**
+     * 鑾峰彇鍩虹BOM璇︾粏淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('bs:ProductBom:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(bsProductBomInfoService.selectBsProductBomInfoById(id));
+    }
+
+    /**
+     * 鏂板鍩虹BOM
+     */
+    @PreAuthorize("@ss.hasPermi('bs:ProductBom:add')")
+    @Log(title = "鍩虹BOM", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody BsProductBomInfo bsProductBomInfo)
+    {
+        bsProductBomInfo.setCreateBy(getUsername());
+        bsProductBomInfo.setCreateTime(DateUtils.getNowDate());
+        return toAjax(bsProductBomInfoService.insertBsProductBomInfo(bsProductBomInfo));
+    }
+
+    /**
+     * 淇敼鍩虹BOM
+     */
+    @PreAuthorize("@ss.hasPermi('bs:ProductBom:edit')")
+    @Log(title = "鍩虹BOM", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody BsProductBomInfo bsProductBomInfo)
+    {
+        bsProductBomInfo.setUpdateBy(getUsername());
+        bsProductBomInfo.setUpdateTime(DateUtils.getNowDate());
+        return toAjax(bsProductBomInfoService.updateBsProductBomInfo(bsProductBomInfo));
+    }
+
+    /**
+     * 鍒犻櫎鍩虹BOM
+     */
+    @PreAuthorize("@ss.hasPermi('bs:ProductBom:remove')")
+    @Log(title = "鍩虹BOM", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(bsProductBomInfoService.deleteBsProductBomInfoByIds(ids));
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/productBom/domain/BsProductBomInfo.java b/jcdm-main/src/main/java/com/jcdm/main/bs/productBom/domain/BsProductBomInfo.java
new file mode 100644
index 0000000..f563d41
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/productBom/domain/BsProductBomInfo.java
@@ -0,0 +1,194 @@
+package com.jcdm.main.bs.productBom.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.core.domain.BaseEntity;
+
+/**
+ * 鍩虹BOM瀵硅薄 bs_product_bom_info
+ * 
+ * @author yyt
+ * @date 2023-12-11
+ */
+public class BsProductBomInfo extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 涓婚敭id */
+    private Long id;
+
+    /** BOM缂栫爜 */
+    @Excel(name = "BOM缂栫爜")
+    private String bomCode;
+
+    /** BOM鍚嶇О */
+    @Excel(name = "BOM鍚嶇О")
+    private String bomName;
+
+    /** 浜у搧缂栫爜 */
+    @Excel(name = "浜у搧缂栫爜")
+    private String productCode;
+
+    /** 浜у搧鍚嶇О */
+    @Excel(name = "浜у搧鍚嶇О")
+    private String productName;
+
+    /** 鐗堟湰 */
+    @Excel(name = "鐗堟湰")
+    private String version;
+
+    /** 鐘舵��(瀛楀吀) */
+    @Excel(name = "鐘舵��(瀛楀吀)")
+    private String status;
+
+    /** 棰勭暀瀛楁1 */
+    @Excel(name = "棰勭暀瀛楁1")
+    private String spareField1;
+
+    /** 棰勭暀瀛楁2 */
+    @Excel(name = "棰勭暀瀛楁2")
+    private String spareField2;
+
+    /** 鍒涘缓鐢ㄦ埛 */
+    @Excel(name = "鍒涘缓鐢ㄦ埛")
+    private String createUser;
+
+    /** 鏇存敼鐢ㄦ埛 */
+    @Excel(name = "鏇存敼鐢ㄦ埛")
+    private String updateUser;
+
+    /** 鏁版嵁鏉ユ簮 */
+    @Excel(name = "鏁版嵁鏉ユ簮")
+    private String dataSource;
+
+    public void setId(Long id) 
+    {
+        this.id = id;
+    }
+
+    public Long getId() 
+    {
+        return id;
+    }
+    public void setBomCode(String bomCode) 
+    {
+        this.bomCode = bomCode;
+    }
+
+    public String getBomCode() 
+    {
+        return bomCode;
+    }
+    public void setBomName(String bomName) 
+    {
+        this.bomName = bomName;
+    }
+
+    public String getBomName() 
+    {
+        return bomName;
+    }
+    public void setProductCode(String productCode) 
+    {
+        this.productCode = productCode;
+    }
+
+    public String getProductCode() 
+    {
+        return productCode;
+    }
+    public void setProductName(String productName) 
+    {
+        this.productName = productName;
+    }
+
+    public String getProductName() 
+    {
+        return productName;
+    }
+    public void setVersion(String version) 
+    {
+        this.version = version;
+    }
+
+    public String getVersion() 
+    {
+        return version;
+    }
+    public void setStatus(String status) 
+    {
+        this.status = status;
+    }
+
+    public String getStatus() 
+    {
+        return status;
+    }
+    public void setSpareField1(String spareField1) 
+    {
+        this.spareField1 = spareField1;
+    }
+
+    public String getSpareField1() 
+    {
+        return spareField1;
+    }
+    public void setSpareField2(String spareField2) 
+    {
+        this.spareField2 = spareField2;
+    }
+
+    public String getSpareField2() 
+    {
+        return spareField2;
+    }
+    public void setCreateUser(String createUser) 
+    {
+        this.createUser = createUser;
+    }
+
+    public String getCreateUser() 
+    {
+        return createUser;
+    }
+    public void setUpdateUser(String updateUser) 
+    {
+        this.updateUser = updateUser;
+    }
+
+    public String getUpdateUser() 
+    {
+        return updateUser;
+    }
+    public void setDataSource(String dataSource) 
+    {
+        this.dataSource = dataSource;
+    }
+
+    public String getDataSource() 
+    {
+        return dataSource;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("bomCode", getBomCode())
+            .append("bomName", getBomName())
+            .append("productCode", getProductCode())
+            .append("productName", getProductName())
+            .append("version", getVersion())
+            .append("status", getStatus())
+            .append("spareField1", getSpareField1())
+            .append("spareField2", getSpareField2())
+            .append("remark", getRemark())
+            .append("createUser", getCreateUser())
+            .append("createTime", getCreateTime())
+            .append("updateUser", getUpdateUser())
+            .append("updateTime", getUpdateTime())
+            .append("dataSource", getDataSource())
+            .toString();
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/productBom/mapper/BsProductBomInfoMapper.java b/jcdm-main/src/main/java/com/jcdm/main/bs/productBom/mapper/BsProductBomInfoMapper.java
new file mode 100644
index 0000000..4a18d64
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/productBom/mapper/BsProductBomInfoMapper.java
@@ -0,0 +1,63 @@
+package com.jcdm.main.bs.productBom.mapper;
+
+import com.jcdm.main.bs.productBom.domain.BsProductBomInfo;
+
+
+import java.util.List;
+
+/**
+ * 鍩虹BOMMapper鎺ュ彛
+ * 
+ * @author yyt
+ * @date 2023-12-11
+ */
+public interface BsProductBomInfoMapper 
+{
+    /**
+     * 鏌ヨ鍩虹BOM
+     * 
+     * @param id 鍩虹BOM涓婚敭
+     * @return 鍩虹BOM
+     */
+    public BsProductBomInfo selectBsProductBomInfoById(Long id);
+
+    /**
+     * 鏌ヨ鍩虹BOM鍒楄〃
+     * 
+     * @param bsProductBomInfo 鍩虹BOM
+     * @return 鍩虹BOM闆嗗悎
+     */
+    public List<BsProductBomInfo> selectBsProductBomInfoList(BsProductBomInfo bsProductBomInfo);
+
+    /**
+     * 鏂板鍩虹BOM
+     * 
+     * @param bsProductBomInfo 鍩虹BOM
+     * @return 缁撴灉
+     */
+    public int insertBsProductBomInfo(BsProductBomInfo bsProductBomInfo);
+
+    /**
+     * 淇敼鍩虹BOM
+     * 
+     * @param bsProductBomInfo 鍩虹BOM
+     * @return 缁撴灉
+     */
+    public int updateBsProductBomInfo(BsProductBomInfo bsProductBomInfo);
+
+    /**
+     * 鍒犻櫎鍩虹BOM
+     * 
+     * @param id 鍩虹BOM涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteBsProductBomInfoById(Long id);
+
+    /**
+     * 鎵归噺鍒犻櫎鍩虹BOM
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteBsProductBomInfoByIds(Long[] ids);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/productBom/service/IBsProductBomInfoService.java b/jcdm-main/src/main/java/com/jcdm/main/bs/productBom/service/IBsProductBomInfoService.java
new file mode 100644
index 0000000..7867bb9
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/productBom/service/IBsProductBomInfoService.java
@@ -0,0 +1,62 @@
+package com.jcdm.main.bs.productBom.service;
+
+import com.jcdm.main.bs.productBom.domain.BsProductBomInfo;
+
+import java.util.List;
+
+/**
+ * 鍩虹BOMService鎺ュ彛
+ * 
+ * @author yyt
+ * @date 2023-12-11
+ */
+public interface IBsProductBomInfoService 
+{
+    /**
+     * 鏌ヨ鍩虹BOM
+     * 
+     * @param id 鍩虹BOM涓婚敭
+     * @return 鍩虹BOM
+     */
+    public BsProductBomInfo selectBsProductBomInfoById(Long id);
+
+    /**
+     * 鏌ヨ鍩虹BOM鍒楄〃
+     * 
+     * @param bsProductBomInfo 鍩虹BOM
+     * @return 鍩虹BOM闆嗗悎
+     */
+    public List<BsProductBomInfo> selectBsProductBomInfoList(BsProductBomInfo bsProductBomInfo);
+
+    /**
+     * 鏂板鍩虹BOM
+     * 
+     * @param bsProductBomInfo 鍩虹BOM
+     * @return 缁撴灉
+     */
+    public int insertBsProductBomInfo(BsProductBomInfo bsProductBomInfo);
+
+    /**
+     * 淇敼鍩虹BOM
+     * 
+     * @param bsProductBomInfo 鍩虹BOM
+     * @return 缁撴灉
+     */
+    public int updateBsProductBomInfo(BsProductBomInfo bsProductBomInfo);
+
+    /**
+     * 鎵归噺鍒犻櫎鍩虹BOM
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鍩虹BOM涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteBsProductBomInfoByIds(Long[] ids);
+
+    /**
+     * 鍒犻櫎鍩虹BOM淇℃伅
+     * 
+     * @param id 鍩虹BOM涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteBsProductBomInfoById(Long id);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/productBom/service/impl/BsProductBomInfoServiceImpl.java b/jcdm-main/src/main/java/com/jcdm/main/bs/productBom/service/impl/BsProductBomInfoServiceImpl.java
new file mode 100644
index 0000000..7051fb7
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/productBom/service/impl/BsProductBomInfoServiceImpl.java
@@ -0,0 +1,97 @@
+package com.jcdm.main.bs.productBom.service.impl;
+
+import java.util.List;
+import com.jcdm.common.utils.DateUtils;
+import com.jcdm.main.bs.productBom.domain.BsProductBomInfo;
+import com.jcdm.main.bs.productBom.mapper.BsProductBomInfoMapper;
+import com.jcdm.main.bs.productBom.service.IBsProductBomInfoService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+
+/**
+ * 鍩虹BOMService涓氬姟灞傚鐞�
+ * 
+ * @author yyt
+ * @date 2023-12-11
+ */
+@Service
+public class BsProductBomInfoServiceImpl implements IBsProductBomInfoService
+{
+    @Autowired
+    private BsProductBomInfoMapper bsProductBomInfoMapper;
+
+    /**
+     * 鏌ヨ鍩虹BOM
+     * 
+     * @param id 鍩虹BOM涓婚敭
+     * @return 鍩虹BOM
+     */
+    @Override
+    public BsProductBomInfo selectBsProductBomInfoById(Long id)
+    {
+        return bsProductBomInfoMapper.selectBsProductBomInfoById(id);
+    }
+
+    /**
+     * 鏌ヨ鍩虹BOM鍒楄〃
+     * 
+     * @param bsProductBomInfo 鍩虹BOM
+     * @return 鍩虹BOM
+     */
+    @Override
+    public List<BsProductBomInfo> selectBsProductBomInfoList(BsProductBomInfo bsProductBomInfo)
+    {
+        return bsProductBomInfoMapper.selectBsProductBomInfoList(bsProductBomInfo);
+    }
+
+    /**
+     * 鏂板鍩虹BOM
+     * 
+     * @param bsProductBomInfo 鍩虹BOM
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertBsProductBomInfo(BsProductBomInfo bsProductBomInfo)
+    {
+        bsProductBomInfo.setCreateTime(DateUtils.getNowDate());
+        return bsProductBomInfoMapper.insertBsProductBomInfo(bsProductBomInfo);
+    }
+
+    /**
+     * 淇敼鍩虹BOM
+     * 
+     * @param bsProductBomInfo 鍩虹BOM
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateBsProductBomInfo(BsProductBomInfo bsProductBomInfo)
+    {
+        bsProductBomInfo.setUpdateTime(DateUtils.getNowDate());
+        return bsProductBomInfoMapper.updateBsProductBomInfo(bsProductBomInfo);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎鍩虹BOM
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鍩虹BOM涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteBsProductBomInfoByIds(Long[] ids)
+    {
+        return bsProductBomInfoMapper.deleteBsProductBomInfoByIds(ids);
+    }
+
+    /**
+     * 鍒犻櫎鍩虹BOM淇℃伅
+     * 
+     * @param id 鍩虹BOM涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteBsProductBomInfoById(Long id)
+    {
+        return bsProductBomInfoMapper.deleteBsProductBomInfoById(id);
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/productBomChild/controller/BsProductBomChildInfoController.java b/jcdm-main/src/main/java/com/jcdm/main/bs/productBomChild/controller/BsProductBomChildInfoController.java
new file mode 100644
index 0000000..5d5f7ae
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/productBomChild/controller/BsProductBomChildInfoController.java
@@ -0,0 +1,110 @@
+package com.jcdm.main.bs.productBomChild.controller;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.jcdm.common.utils.DateUtils;
+import com.jcdm.main.bs.productBomChild.domain.BsProductBomChildInfo;
+import com.jcdm.main.bs.productBomChild.service.IBsProductBomChildInfoService;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.common.utils.poi.ExcelUtil;
+import com.jcdm.common.core.page.TableDataInfo;
+
+/**
+ * 鍩虹BOM瀛愪俊鎭疌ontroller
+ * 
+ * @author yyt
+ * @date 2023-12-11
+ */
+@RestController
+@RequestMapping("/bs/ProductBomChild")
+public class BsProductBomChildInfoController extends BaseController
+{
+    @Autowired
+    private IBsProductBomChildInfoService bsProductBomChildInfoService;
+
+    /**
+     * 鏌ヨ鍩虹BOM瀛愪俊鎭垪琛�
+     */
+    @PreAuthorize("@ss.hasPermi('bs:ProductBomChild:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(BsProductBomChildInfo bsProductBomChildInfo)
+    {
+        startPage();
+        List<BsProductBomChildInfo> list = bsProductBomChildInfoService.selectBsProductBomChildInfoList(bsProductBomChildInfo);
+        return getDataTable(list);
+    }
+
+    /**
+     * 瀵煎嚭鍩虹BOM瀛愪俊鎭垪琛�
+     */
+    @PreAuthorize("@ss.hasPermi('bs:ProductBomChild:export')")
+    @Log(title = "鍩虹BOM瀛愪俊鎭�", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, BsProductBomChildInfo bsProductBomChildInfo)
+    {
+        List<BsProductBomChildInfo> list = bsProductBomChildInfoService.selectBsProductBomChildInfoList(bsProductBomChildInfo);
+        ExcelUtil<BsProductBomChildInfo> util = new ExcelUtil<BsProductBomChildInfo>(BsProductBomChildInfo.class);
+        util.exportExcel(response, list, "鍩虹BOM瀛愪俊鎭暟鎹�");
+    }
+
+    /**
+     * 鑾峰彇鍩虹BOM瀛愪俊鎭缁嗕俊鎭�
+     */
+    @PreAuthorize("@ss.hasPermi('bs:ProductBomChild:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(bsProductBomChildInfoService.selectBsProductBomChildInfoById(id));
+    }
+
+    /**
+     * 鏂板鍩虹BOM瀛愪俊鎭�
+     */
+    @PreAuthorize("@ss.hasPermi('bs:ProductBomChild:add')")
+    @Log(title = "鍩虹BOM瀛愪俊鎭�", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody BsProductBomChildInfo bsProductBomChildInfo)
+    {
+        bsProductBomChildInfo.setCreateBy(getUsername());
+        bsProductBomChildInfo.setCreateTime(DateUtils.getNowDate());
+        return toAjax(bsProductBomChildInfoService.insertBsProductBomChildInfo(bsProductBomChildInfo));
+    }
+
+    /**
+     * 淇敼鍩虹BOM瀛愪俊鎭�
+     */
+    @PreAuthorize("@ss.hasPermi('bs:ProductBomChild:edit')")
+    @Log(title = "鍩虹BOM瀛愪俊鎭�", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody BsProductBomChildInfo bsProductBomChildInfo)
+    {
+        bsProductBomChildInfo.setUpdateBy(getUsername());
+        bsProductBomChildInfo.setUpdateTime(DateUtils.getNowDate());
+        return toAjax(bsProductBomChildInfoService.updateBsProductBomChildInfo(bsProductBomChildInfo));
+    }
+
+    /**
+     * 鍒犻櫎鍩虹BOM瀛愪俊鎭�
+     */
+    @PreAuthorize("@ss.hasPermi('bs:ProductBomChild:remove')")
+    @Log(title = "鍩虹BOM瀛愪俊鎭�", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(bsProductBomChildInfoService.deleteBsProductBomChildInfoByIds(ids));
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/productBomChild/domain/BsProductBomChildInfo.java b/jcdm-main/src/main/java/com/jcdm/main/bs/productBomChild/domain/BsProductBomChildInfo.java
new file mode 100644
index 0000000..9157a31
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/productBomChild/domain/BsProductBomChildInfo.java
@@ -0,0 +1,191 @@
+package com.jcdm.main.bs.productBomChild.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.core.domain.BaseEntity;
+
+/**
+ * 鍩虹BOM瀛愪俊鎭璞� bs_product_bom_child_info
+ * 
+ * @author yyt
+ * @date 2023-12-11
+ */
+public class BsProductBomChildInfo extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 涓婚敭id */
+    private Long id;
+
+    /** 宸ュ簭缂栫爜 */
+    @Excel(name = "宸ュ簭缂栫爜")
+    private String opCode;
+
+    /** 宸ュ簭鍚嶇О */
+    @Excel(name = "宸ュ簭鍚嶇О")
+    private String opName;
+
+    /** 鐗╂枡缂栫爜 */
+    @Excel(name = "鐗╂枡缂栫爜")
+    private String materialCode;
+
+    /** 鐗╂枡鍚嶇О */
+    @Excel(name = "鐗╂枡鍚嶇О")
+    private String materialName;
+
+    /** 鍗曡�� */
+    @Excel(name = "鍗曡��")
+    private String costQty;
+
+    /** 鍗曚綅 */
+    @Excel(name = "鍗曚綅")
+    private String unit;
+
+    /** 棰勭暀瀛楁1 */
+    @Excel(name = "棰勭暀瀛楁1")
+    private String spareField1;
+
+    /** 棰勭暀瀛楁2 */
+    @Excel(name = "棰勭暀瀛楁2")
+    private String spareField2;
+
+    /** 棰勭暀瀛楁3 */
+    @Excel(name = "棰勭暀瀛楁3")
+    private String spareField3;
+
+    /** BOM缂栫爜 */
+    @Excel(name = "BOM缂栫爜")
+    private String bomCode;
+
+    /** BOM涓昏〃ID */
+    private Long bomInfoId;
+
+    public void setId(Long id) 
+    {
+        this.id = id;
+    }
+
+    public Long getId() 
+    {
+        return id;
+    }
+    public void setOpCode(String opCode) 
+    {
+        this.opCode = opCode;
+    }
+
+    public String getOpCode() 
+    {
+        return opCode;
+    }
+    public void setOpName(String opName) 
+    {
+        this.opName = opName;
+    }
+
+    public String getOpName() 
+    {
+        return opName;
+    }
+    public void setMaterialCode(String materialCode) 
+    {
+        this.materialCode = materialCode;
+    }
+
+    public String getMaterialCode() 
+    {
+        return materialCode;
+    }
+    public void setMaterialName(String materialName) 
+    {
+        this.materialName = materialName;
+    }
+
+    public String getMaterialName() 
+    {
+        return materialName;
+    }
+    public void setCostQty(String costQty) 
+    {
+        this.costQty = costQty;
+    }
+
+    public String getCostQty() 
+    {
+        return costQty;
+    }
+    public void setUnit(String unit) 
+    {
+        this.unit = unit;
+    }
+
+    public String getUnit() 
+    {
+        return unit;
+    }
+    public void setSpareField1(String spareField1) 
+    {
+        this.spareField1 = spareField1;
+    }
+
+    public String getSpareField1() 
+    {
+        return spareField1;
+    }
+    public void setSpareField2(String spareField2) 
+    {
+        this.spareField2 = spareField2;
+    }
+
+    public String getSpareField2() 
+    {
+        return spareField2;
+    }
+    public void setSpareField3(String spareField3) 
+    {
+        this.spareField3 = spareField3;
+    }
+
+    public String getSpareField3() 
+    {
+        return spareField3;
+    }
+    public void setBomCode(String bomCode) 
+    {
+        this.bomCode = bomCode;
+    }
+
+    public String getBomCode() 
+    {
+        return bomCode;
+    }
+    public void setBomInfoId(Long bomInfoId) 
+    {
+        this.bomInfoId = bomInfoId;
+    }
+
+    public Long getBomInfoId() 
+    {
+        return bomInfoId;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("opCode", getOpCode())
+            .append("opName", getOpName())
+            .append("materialCode", getMaterialCode())
+            .append("materialName", getMaterialName())
+            .append("costQty", getCostQty())
+            .append("unit", getUnit())
+            .append("spareField1", getSpareField1())
+            .append("spareField2", getSpareField2())
+            .append("spareField3", getSpareField3())
+            .append("remark", getRemark())
+            .append("bomCode", getBomCode())
+            .append("bomInfoId", getBomInfoId())
+            .toString();
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/productBomChild/mapper/BsProductBomChildInfoMapper.java b/jcdm-main/src/main/java/com/jcdm/main/bs/productBomChild/mapper/BsProductBomChildInfoMapper.java
new file mode 100644
index 0000000..437d525
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/productBomChild/mapper/BsProductBomChildInfoMapper.java
@@ -0,0 +1,62 @@
+package com.jcdm.main.bs.productBomChild.mapper;
+
+import com.jcdm.main.bs.productBomChild.domain.BsProductBomChildInfo;
+
+import java.util.List;
+
+/**
+ * 鍩虹BOM瀛愪俊鎭疢apper鎺ュ彛
+ * 
+ * @author yyt
+ * @date 2023-12-11
+ */
+public interface BsProductBomChildInfoMapper 
+{
+    /**
+     * 鏌ヨ鍩虹BOM瀛愪俊鎭�
+     * 
+     * @param id 鍩虹BOM瀛愪俊鎭富閿�
+     * @return 鍩虹BOM瀛愪俊鎭�
+     */
+    public BsProductBomChildInfo selectBsProductBomChildInfoById(Long id);
+
+    /**
+     * 鏌ヨ鍩虹BOM瀛愪俊鎭垪琛�
+     * 
+     * @param bsProductBomChildInfo 鍩虹BOM瀛愪俊鎭�
+     * @return 鍩虹BOM瀛愪俊鎭泦鍚�
+     */
+    public List<BsProductBomChildInfo> selectBsProductBomChildInfoList(BsProductBomChildInfo bsProductBomChildInfo);
+
+    /**
+     * 鏂板鍩虹BOM瀛愪俊鎭�
+     * 
+     * @param bsProductBomChildInfo 鍩虹BOM瀛愪俊鎭�
+     * @return 缁撴灉
+     */
+    public int insertBsProductBomChildInfo(BsProductBomChildInfo bsProductBomChildInfo);
+
+    /**
+     * 淇敼鍩虹BOM瀛愪俊鎭�
+     * 
+     * @param bsProductBomChildInfo 鍩虹BOM瀛愪俊鎭�
+     * @return 缁撴灉
+     */
+    public int updateBsProductBomChildInfo(BsProductBomChildInfo bsProductBomChildInfo);
+
+    /**
+     * 鍒犻櫎鍩虹BOM瀛愪俊鎭�
+     * 
+     * @param id 鍩虹BOM瀛愪俊鎭富閿�
+     * @return 缁撴灉
+     */
+    public int deleteBsProductBomChildInfoById(Long id);
+
+    /**
+     * 鎵归噺鍒犻櫎鍩虹BOM瀛愪俊鎭�
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteBsProductBomChildInfoByIds(Long[] ids);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/productBomChild/service/IBsProductBomChildInfoService.java b/jcdm-main/src/main/java/com/jcdm/main/bs/productBomChild/service/IBsProductBomChildInfoService.java
new file mode 100644
index 0000000..96e414e
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/productBomChild/service/IBsProductBomChildInfoService.java
@@ -0,0 +1,63 @@
+package com.jcdm.main.bs.productBomChild.service;
+
+import com.jcdm.main.bs.productBomChild.domain.BsProductBomChildInfo;
+
+import java.util.List;
+
+
+/**
+ * 鍩虹BOM瀛愪俊鎭疭ervice鎺ュ彛
+ * 
+ * @author yyt
+ * @date 2023-12-11
+ */
+public interface IBsProductBomChildInfoService 
+{
+    /**
+     * 鏌ヨ鍩虹BOM瀛愪俊鎭�
+     * 
+     * @param id 鍩虹BOM瀛愪俊鎭富閿�
+     * @return 鍩虹BOM瀛愪俊鎭�
+     */
+    public BsProductBomChildInfo selectBsProductBomChildInfoById(Long id);
+
+    /**
+     * 鏌ヨ鍩虹BOM瀛愪俊鎭垪琛�
+     * 
+     * @param bsProductBomChildInfo 鍩虹BOM瀛愪俊鎭�
+     * @return 鍩虹BOM瀛愪俊鎭泦鍚�
+     */
+    public List<BsProductBomChildInfo> selectBsProductBomChildInfoList(BsProductBomChildInfo bsProductBomChildInfo);
+
+    /**
+     * 鏂板鍩虹BOM瀛愪俊鎭�
+     * 
+     * @param bsProductBomChildInfo 鍩虹BOM瀛愪俊鎭�
+     * @return 缁撴灉
+     */
+    public int insertBsProductBomChildInfo(BsProductBomChildInfo bsProductBomChildInfo);
+
+    /**
+     * 淇敼鍩虹BOM瀛愪俊鎭�
+     * 
+     * @param bsProductBomChildInfo 鍩虹BOM瀛愪俊鎭�
+     * @return 缁撴灉
+     */
+    public int updateBsProductBomChildInfo(BsProductBomChildInfo bsProductBomChildInfo);
+
+    /**
+     * 鎵归噺鍒犻櫎鍩虹BOM瀛愪俊鎭�
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鍩虹BOM瀛愪俊鎭富閿泦鍚�
+     * @return 缁撴灉
+     */
+    public int deleteBsProductBomChildInfoByIds(Long[] ids);
+
+    /**
+     * 鍒犻櫎鍩虹BOM瀛愪俊鎭俊鎭�
+     * 
+     * @param id 鍩虹BOM瀛愪俊鎭富閿�
+     * @return 缁撴灉
+     */
+    public int deleteBsProductBomChildInfoById(Long id);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/productBomChild/service/impl/BsProductBomChildInfoServiceImpl.java b/jcdm-main/src/main/java/com/jcdm/main/bs/productBomChild/service/impl/BsProductBomChildInfoServiceImpl.java
new file mode 100644
index 0000000..a8abeb0
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/productBomChild/service/impl/BsProductBomChildInfoServiceImpl.java
@@ -0,0 +1,94 @@
+package com.jcdm.main.bs.productBomChild.service.impl;
+
+import java.util.List;
+
+import com.jcdm.main.bs.productBomChild.domain.BsProductBomChildInfo;
+import com.jcdm.main.bs.productBomChild.mapper.BsProductBomChildInfoMapper;
+import com.jcdm.main.bs.productBomChild.service.IBsProductBomChildInfoService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * 鍩虹BOM瀛愪俊鎭疭ervice涓氬姟灞傚鐞�
+ * 
+ * @author yyt
+ * @date 2023-12-11
+ */
+@Service
+public class BsProductBomChildInfoServiceImpl implements IBsProductBomChildInfoService
+{
+    @Autowired
+    private BsProductBomChildInfoMapper bsProductBomChildInfoMapper;
+
+    /**
+     * 鏌ヨ鍩虹BOM瀛愪俊鎭�
+     * 
+     * @param id 鍩虹BOM瀛愪俊鎭富閿�
+     * @return 鍩虹BOM瀛愪俊鎭�
+     */
+    @Override
+    public BsProductBomChildInfo selectBsProductBomChildInfoById(Long id)
+    {
+        return bsProductBomChildInfoMapper.selectBsProductBomChildInfoById(id);
+    }
+
+    /**
+     * 鏌ヨ鍩虹BOM瀛愪俊鎭垪琛�
+     * 
+     * @param bsProductBomChildInfo 鍩虹BOM瀛愪俊鎭�
+     * @return 鍩虹BOM瀛愪俊鎭�
+     */
+    @Override
+    public List<BsProductBomChildInfo> selectBsProductBomChildInfoList(BsProductBomChildInfo bsProductBomChildInfo)
+    {
+        return bsProductBomChildInfoMapper.selectBsProductBomChildInfoList(bsProductBomChildInfo);
+    }
+
+    /**
+     * 鏂板鍩虹BOM瀛愪俊鎭�
+     * 
+     * @param bsProductBomChildInfo 鍩虹BOM瀛愪俊鎭�
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertBsProductBomChildInfo(BsProductBomChildInfo bsProductBomChildInfo)
+    {
+        return bsProductBomChildInfoMapper.insertBsProductBomChildInfo(bsProductBomChildInfo);
+    }
+
+    /**
+     * 淇敼鍩虹BOM瀛愪俊鎭�
+     * 
+     * @param bsProductBomChildInfo 鍩虹BOM瀛愪俊鎭�
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateBsProductBomChildInfo(BsProductBomChildInfo bsProductBomChildInfo)
+    {
+        return bsProductBomChildInfoMapper.updateBsProductBomChildInfo(bsProductBomChildInfo);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎鍩虹BOM瀛愪俊鎭�
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鍩虹BOM瀛愪俊鎭富閿�
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteBsProductBomChildInfoByIds(Long[] ids)
+    {
+        return bsProductBomChildInfoMapper.deleteBsProductBomChildInfoByIds(ids);
+    }
+
+    /**
+     * 鍒犻櫎鍩虹BOM瀛愪俊鎭俊鎭�
+     * 
+     * @param id 鍩虹BOM瀛愪俊鎭富閿�
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteBsProductBomChildInfoById(Long id)
+    {
+        return bsProductBomChildInfoMapper.deleteBsProductBomChildInfoById(id);
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/technologyRoute/controller/BsTechnologyRouteInfoController.java b/jcdm-main/src/main/java/com/jcdm/main/bs/technologyRoute/controller/BsTechnologyRouteInfoController.java
new file mode 100644
index 0000000..391441d
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/technologyRoute/controller/BsTechnologyRouteInfoController.java
@@ -0,0 +1,116 @@
+package com.jcdm.main.bs.technologyRoute.controller;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.jcdm.main.bs.technologyRoute.domain.BsTechnologyRouteInfo;
+import com.jcdm.main.bs.technologyRoute.service.IBsTechnologyRouteInfoService;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.common.utils.poi.ExcelUtil;
+import com.jcdm.common.core.page.TableDataInfo;
+
+/**
+ * 宸ヨ壓娴佺▼Controller
+ * 
+ * @author ruimin
+ * @date 2023-12-09
+ */
+@RestController
+@RequestMapping("/bs/technologyRoute")
+public class BsTechnologyRouteInfoController extends BaseController
+{
+    @Autowired
+    private IBsTechnologyRouteInfoService bsTechnologyRouteInfoService;
+
+    /**
+     * 鏌ヨ宸ヨ壓娴佺▼鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('bs:technologyRoute:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(BsTechnologyRouteInfo bsTechnologyRouteInfo)
+    {
+        startPage();
+        List<BsTechnologyRouteInfo> list = bsTechnologyRouteInfoService.selectBsTechnologyRouteInfoList(bsTechnologyRouteInfo);
+        return getDataTable(list);
+    }
+
+    /**
+     * 瀵煎嚭宸ヨ壓娴佺▼鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('bs:technologyRoute:export')")
+    @Log(title = "宸ヨ壓娴佺▼", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, BsTechnologyRouteInfo bsTechnologyRouteInfo)
+    {
+        List<BsTechnologyRouteInfo> list = bsTechnologyRouteInfoService.selectBsTechnologyRouteInfoList(bsTechnologyRouteInfo);
+        ExcelUtil<BsTechnologyRouteInfo> util = new ExcelUtil<BsTechnologyRouteInfo>(BsTechnologyRouteInfo.class);
+        util.exportExcel(response, list, "宸ヨ壓娴佺▼鏁版嵁");
+    }
+
+    /**
+     * 鑾峰彇宸ヨ壓娴佺▼璇︾粏淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('bs:technologyRoute:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(bsTechnologyRouteInfoService.selectBsTechnologyRouteInfoById(id));
+    }
+
+    /**
+     * 鏂板宸ヨ壓娴佺▼
+     */
+    @PreAuthorize("@ss.hasPermi('bs:technologyRoute:add')")
+    @Log(title = "宸ヨ壓娴佺▼", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody BsTechnologyRouteInfo bsTechnologyRouteInfo)
+    {
+        return toAjax(bsTechnologyRouteInfoService.insertBsTechnologyRouteInfo(bsTechnologyRouteInfo));
+    }
+
+    /**
+     * 淇敼宸ヨ壓娴佺▼
+     */
+    @PreAuthorize("@ss.hasPermi('bs:technologyRoute:edit')")
+    @Log(title = "宸ヨ壓娴佺▼", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody BsTechnologyRouteInfo bsTechnologyRouteInfo)
+    {
+        return toAjax(bsTechnologyRouteInfoService.updateBsTechnologyRouteInfo(bsTechnologyRouteInfo));
+    }
+
+    /**
+     * 淇敼宸ヨ壓娴佺▼浠ュ強瀛愬伐鑹�
+     */
+    @PreAuthorize("@ss.hasPermi('bs:technologyRouteAndChild:edit')")
+    @Log(title = "宸ヨ壓娴佺▼And瀛愪俊鎭�", businessType = BusinessType.UPDATE)
+    @PutMapping("/technologyRouteAndChild")
+    public AjaxResult technologyRouteAndChild(@RequestBody BsTechnologyRouteInfo bsTechnologyRouteInfo)
+    {
+        return toAjax(bsTechnologyRouteInfoService.updateBsTechnologyRouteAndChildInfo(bsTechnologyRouteInfo));
+    }
+
+    /**
+     * 鍒犻櫎宸ヨ壓娴佺▼
+     */
+    @PreAuthorize("@ss.hasPermi('bs:technologyRoute:remove')")
+    @Log(title = "宸ヨ壓娴佺▼", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(bsTechnologyRouteInfoService.deleteBsTechnologyRouteInfoByIds(ids));
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/technologyRoute/domain/BsTechnologyRouteInfo.java b/jcdm-main/src/main/java/com/jcdm/main/bs/technologyRoute/domain/BsTechnologyRouteInfo.java
new file mode 100644
index 0000000..dcb3daf
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/technologyRoute/domain/BsTechnologyRouteInfo.java
@@ -0,0 +1,218 @@
+package com.jcdm.main.bs.technologyRoute.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.core.domain.BaseEntity;
+
+/**
+ * 宸ヨ壓娴佺▼瀵硅薄 bs_technology_route_info
+ * 
+ * @author ruimin
+ * @date 2023-12-09
+ */
+public class BsTechnologyRouteInfo extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 涓婚敭id */
+    private Long id;
+
+    /** 宸ヨ壓娴佺▼缂栫爜 */
+    @Excel(name = "宸ヨ壓娴佺▼缂栫爜")
+    private String routeCode;
+
+    /** 宸ヨ壓娴佺▼鍚嶇О */
+    @Excel(name = "宸ヨ壓娴佺▼鍚嶇О")
+    private String routeName;
+
+    /** 浜у搧缂栫爜 */
+    @Excel(name = "浜у搧缂栫爜")
+    private String productCode;
+
+    /** 浜у搧鍚嶇О */
+    @Excel(name = "浜у搧鍚嶇О")
+    private String productName;
+
+    /** 鐗堟湰 */
+    @Excel(name = "鐗堟湰")
+    private String version;
+
+    /** 鐘舵��(瀛楀吀) */
+    @Excel(name = "鐘舵��(瀛楀吀)")
+    private String status;
+
+    /** 鏁版嵁鏉ユ簮 */
+    @Excel(name = "鏁版嵁鏉ユ簮")
+    private String dataSource;
+
+    /** 鍒涘缓鐢ㄦ埛 */
+    @Excel(name = "鍒涘缓鐢ㄦ埛")
+    private String createUser;
+
+    /** 鏇存敼鐢ㄦ埛 */
+    @Excel(name = "鏇存敼鐢ㄦ埛")
+    private String updateUser;
+
+    /** 棰勭暀瀛楁1 */
+    private String spareField1;
+
+    /** 棰勭暀瀛楁2 */
+    private String spareField2;
+
+    /** 棰勭暀瀛楁3 */
+    private String spareField3;
+
+    /** 棰勭暀瀛楁4 */
+    private String spareField4;
+
+    public void setId(Long id) 
+    {
+        this.id = id;
+    }
+
+    public Long getId() 
+    {
+        return id;
+    }
+    public void setRouteCode(String routeCode) 
+    {
+        this.routeCode = routeCode;
+    }
+
+    public String getRouteCode() 
+    {
+        return routeCode;
+    }
+    public void setRouteName(String routeName) 
+    {
+        this.routeName = routeName;
+    }
+
+    public String getRouteName() 
+    {
+        return routeName;
+    }
+    public void setProductCode(String productCode) 
+    {
+        this.productCode = productCode;
+    }
+
+    public String getProductCode() 
+    {
+        return productCode;
+    }
+    public void setProductName(String productName) 
+    {
+        this.productName = productName;
+    }
+
+    public String getProductName() 
+    {
+        return productName;
+    }
+    public void setVersion(String version) 
+    {
+        this.version = version;
+    }
+
+    public String getVersion() 
+    {
+        return version;
+    }
+    public void setStatus(String status) 
+    {
+        this.status = status;
+    }
+
+    public String getStatus() 
+    {
+        return status;
+    }
+    public void setDataSource(String dataSource) 
+    {
+        this.dataSource = dataSource;
+    }
+
+    public String getDataSource() 
+    {
+        return dataSource;
+    }
+    public void setCreateUser(String createUser) 
+    {
+        this.createUser = createUser;
+    }
+
+    public String getCreateUser() 
+    {
+        return createUser;
+    }
+    public void setUpdateUser(String updateUser) 
+    {
+        this.updateUser = updateUser;
+    }
+
+    public String getUpdateUser() 
+    {
+        return updateUser;
+    }
+    public void setSpareField1(String spareField1) 
+    {
+        this.spareField1 = spareField1;
+    }
+
+    public String getSpareField1() 
+    {
+        return spareField1;
+    }
+    public void setSpareField2(String spareField2) 
+    {
+        this.spareField2 = spareField2;
+    }
+
+    public String getSpareField2() 
+    {
+        return spareField2;
+    }
+    public void setSpareField3(String spareField3) 
+    {
+        this.spareField3 = spareField3;
+    }
+
+    public String getSpareField3() 
+    {
+        return spareField3;
+    }
+    public void setSpareField4(String spareField4) 
+    {
+        this.spareField4 = spareField4;
+    }
+
+    public String getSpareField4() 
+    {
+        return spareField4;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("routeCode", getRouteCode())
+            .append("routeName", getRouteName())
+            .append("productCode", getProductCode())
+            .append("productName", getProductName())
+            .append("version", getVersion())
+            .append("status", getStatus())
+            .append("dataSource", getDataSource())
+            .append("remark", getRemark())
+            .append("createUser", getCreateUser())
+            .append("createTime", getCreateTime())
+            .append("updateUser", getUpdateUser())
+            .append("updateTime", getUpdateTime())
+            .append("spareField1", getSpareField1())
+            .append("spareField2", getSpareField2())
+            .append("spareField3", getSpareField3())
+            .append("spareField4", getSpareField4())
+            .toString();
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/technologyRoute/mapper/BsTechnologyRouteInfoMapper.java b/jcdm-main/src/main/java/com/jcdm/main/bs/technologyRoute/mapper/BsTechnologyRouteInfoMapper.java
new file mode 100644
index 0000000..0e072c7
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/technologyRoute/mapper/BsTechnologyRouteInfoMapper.java
@@ -0,0 +1,62 @@
+package com.jcdm.main.bs.technologyRoute.mapper;
+
+import com.jcdm.main.bs.technologyRoute.domain.BsTechnologyRouteInfo;
+
+import java.util.List;
+
+/**
+ * 宸ヨ壓娴佺▼Mapper鎺ュ彛
+ * 
+ * @author ruimin
+ * @date 2023-12-09
+ */
+public interface BsTechnologyRouteInfoMapper 
+{
+    /**
+     * 鏌ヨ宸ヨ壓娴佺▼
+     * 
+     * @param id 宸ヨ壓娴佺▼涓婚敭
+     * @return 宸ヨ壓娴佺▼
+     */
+    public BsTechnologyRouteInfo selectBsTechnologyRouteInfoById(Long id);
+
+    /**
+     * 鏌ヨ宸ヨ壓娴佺▼鍒楄〃
+     * 
+     * @param bsTechnologyRouteInfo 宸ヨ壓娴佺▼
+     * @return 宸ヨ壓娴佺▼闆嗗悎
+     */
+    public List<BsTechnologyRouteInfo> selectBsTechnologyRouteInfoList(BsTechnologyRouteInfo bsTechnologyRouteInfo);
+
+    /**
+     * 鏂板宸ヨ壓娴佺▼
+     * 
+     * @param bsTechnologyRouteInfo 宸ヨ壓娴佺▼
+     * @return 缁撴灉
+     */
+    public int insertBsTechnologyRouteInfo(BsTechnologyRouteInfo bsTechnologyRouteInfo);
+
+    /**
+     * 淇敼宸ヨ壓娴佺▼
+     * 
+     * @param bsTechnologyRouteInfo 宸ヨ壓娴佺▼
+     * @return 缁撴灉
+     */
+    public int updateBsTechnologyRouteInfo(BsTechnologyRouteInfo bsTechnologyRouteInfo);
+
+    /**
+     * 鍒犻櫎宸ヨ壓娴佺▼
+     * 
+     * @param id 宸ヨ壓娴佺▼涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteBsTechnologyRouteInfoById(Long id);
+
+    /**
+     * 鎵归噺鍒犻櫎宸ヨ壓娴佺▼
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteBsTechnologyRouteInfoByIds(Long[] ids);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/technologyRoute/service/IBsTechnologyRouteInfoService.java b/jcdm-main/src/main/java/com/jcdm/main/bs/technologyRoute/service/IBsTechnologyRouteInfoService.java
new file mode 100644
index 0000000..763724c
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/technologyRoute/service/IBsTechnologyRouteInfoService.java
@@ -0,0 +1,64 @@
+package com.jcdm.main.bs.technologyRoute.service;
+
+import com.jcdm.main.bs.technologyRoute.domain.BsTechnologyRouteInfo;
+
+import java.util.List;
+
+/**
+ * 宸ヨ壓娴佺▼Service鎺ュ彛
+ * 
+ * @author ruimin
+ * @date 2023-12-09
+ */
+public interface IBsTechnologyRouteInfoService 
+{
+    /**
+     * 鏌ヨ宸ヨ壓娴佺▼
+     * 
+     * @param id 宸ヨ壓娴佺▼涓婚敭
+     * @return 宸ヨ壓娴佺▼
+     */
+    public BsTechnologyRouteInfo selectBsTechnologyRouteInfoById(Long id);
+
+    /**
+     * 鏌ヨ宸ヨ壓娴佺▼鍒楄〃
+     * 
+     * @param bsTechnologyRouteInfo 宸ヨ壓娴佺▼
+     * @return 宸ヨ壓娴佺▼闆嗗悎
+     */
+    public List<BsTechnologyRouteInfo> selectBsTechnologyRouteInfoList(BsTechnologyRouteInfo bsTechnologyRouteInfo);
+
+    /**
+     * 鏂板宸ヨ壓娴佺▼
+     * 
+     * @param bsTechnologyRouteInfo 宸ヨ壓娴佺▼
+     * @return 缁撴灉
+     */
+    public int insertBsTechnologyRouteInfo(BsTechnologyRouteInfo bsTechnologyRouteInfo);
+
+    /**
+     * 淇敼宸ヨ壓娴佺▼
+     * 
+     * @param bsTechnologyRouteInfo 宸ヨ壓娴佺▼
+     * @return 缁撴灉
+     */
+    public int updateBsTechnologyRouteInfo(BsTechnologyRouteInfo bsTechnologyRouteInfo);
+
+    /**
+     * 鎵归噺鍒犻櫎宸ヨ壓娴佺▼
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑宸ヨ壓娴佺▼涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteBsTechnologyRouteInfoByIds(Long[] ids);
+
+    /**
+     * 鍒犻櫎宸ヨ壓娴佺▼淇℃伅
+     * 
+     * @param id 宸ヨ壓娴佺▼涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteBsTechnologyRouteInfoById(Long id);
+
+    public int updateBsTechnologyRouteAndChildInfo(BsTechnologyRouteInfo bsTechnologyRouteInfo);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/technologyRoute/service/impl/BsTechnologyRouteInfoServiceImpl.java b/jcdm-main/src/main/java/com/jcdm/main/bs/technologyRoute/service/impl/BsTechnologyRouteInfoServiceImpl.java
new file mode 100644
index 0000000..6d856b0
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/technologyRoute/service/impl/BsTechnologyRouteInfoServiceImpl.java
@@ -0,0 +1,119 @@
+package com.jcdm.main.bs.technologyRoute.service.impl;
+
+import java.util.List;
+import com.jcdm.common.utils.DateUtils;
+import com.jcdm.main.bs.domain.BsTechnologyRouteChildInfo;
+import com.jcdm.main.bs.technologyRoute.domain.BsTechnologyRouteInfo;
+import com.jcdm.main.bs.technologyRoute.mapper.BsTechnologyRouteInfoMapper;
+import com.jcdm.main.bs.technologyRoute.service.IBsTechnologyRouteInfoService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.jcdm.main.bs.domain.BsTechnologyRouteChildInfo;
+
+import static org.apache.commons.lang3.SystemUtils.getUserName;
+
+/**
+ * 宸ヨ壓娴佺▼Service涓氬姟灞傚鐞�
+ * 
+ * @author ruimin
+ * @date 2023-12-09
+ */
+@Service
+public class BsTechnologyRouteInfoServiceImpl implements IBsTechnologyRouteInfoService
+{
+    @Autowired
+    private BsTechnologyRouteInfoMapper bsTechnologyRouteInfoMapper;
+
+
+    @Autowired
+    private com.jcdm.main.bs.mapper.BsTechnologyRouteChildInfoMapper bsTechnologyRouteChildInfoMapper;
+
+    /**
+     * 鏌ヨ宸ヨ壓娴佺▼
+     * 
+     * @param id 宸ヨ壓娴佺▼涓婚敭
+     * @return 宸ヨ壓娴佺▼
+     */
+    @Override
+    public BsTechnologyRouteInfo selectBsTechnologyRouteInfoById(Long id)
+    {
+        return bsTechnologyRouteInfoMapper.selectBsTechnologyRouteInfoById(id);
+    }
+
+    /**
+     * 鏌ヨ宸ヨ壓娴佺▼鍒楄〃
+     * 
+     * @param bsTechnologyRouteInfo 宸ヨ壓娴佺▼
+     * @return 宸ヨ壓娴佺▼
+     */
+    @Override
+    public List<BsTechnologyRouteInfo> selectBsTechnologyRouteInfoList(BsTechnologyRouteInfo bsTechnologyRouteInfo)
+    {
+        return bsTechnologyRouteInfoMapper.selectBsTechnologyRouteInfoList(bsTechnologyRouteInfo);
+    }
+
+    /**
+     * 鏂板宸ヨ壓娴佺▼
+     * 
+     * @param bsTechnologyRouteInfo 宸ヨ壓娴佺▼
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertBsTechnologyRouteInfo(BsTechnologyRouteInfo bsTechnologyRouteInfo)
+    {
+        bsTechnologyRouteInfo.setCreateTime(DateUtils.getNowDate());
+        bsTechnologyRouteInfo.setCreateUser(getUserName());
+        return bsTechnologyRouteInfoMapper.insertBsTechnologyRouteInfo(bsTechnologyRouteInfo);
+    }
+
+    /**
+     * 淇敼宸ヨ壓娴佺▼
+     * 
+     * @param bsTechnologyRouteInfo 宸ヨ壓娴佺▼
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateBsTechnologyRouteInfo(BsTechnologyRouteInfo bsTechnologyRouteInfo)
+    {
+        bsTechnologyRouteInfo.setUpdateTime(DateUtils.getNowDate());
+        bsTechnologyRouteInfo.setUpdateUser(getUserName());
+        return bsTechnologyRouteInfoMapper.updateBsTechnologyRouteInfo(bsTechnologyRouteInfo);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎宸ヨ壓娴佺▼
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑宸ヨ壓娴佺▼涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteBsTechnologyRouteInfoByIds(Long[] ids)
+    {
+        return bsTechnologyRouteInfoMapper.deleteBsTechnologyRouteInfoByIds(ids);
+    }
+
+    /**
+     * 鍒犻櫎宸ヨ壓娴佺▼淇℃伅
+     * 
+     * @param id 宸ヨ壓娴佺▼涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteBsTechnologyRouteInfoById(Long id)
+    {
+        return bsTechnologyRouteInfoMapper.deleteBsTechnologyRouteInfoById(id);
+    }
+
+    @Override
+    public int updateBsTechnologyRouteAndChildInfo(BsTechnologyRouteInfo bsTechnologyRouteInfo) {
+        int i = this.updateBsTechnologyRouteInfo(bsTechnologyRouteInfo);
+        com.jcdm.main.bs.domain.BsTechnologyRouteChildInfo  bsTechnologyRouteChildInfo = new com.jcdm.main.bs.domain.BsTechnologyRouteChildInfo();
+        bsTechnologyRouteChildInfo.setId(bsTechnologyRouteInfo.getId());
+        List<BsTechnologyRouteChildInfo> bsTechnologyRouteChildInfos = bsTechnologyRouteChildInfoMapper.selectBsTechnologyRouteChildInfoList(bsTechnologyRouteChildInfo);
+        for (com.jcdm.main.bs.domain.BsTechnologyRouteChildInfo technologyRouteChildInfo : bsTechnologyRouteChildInfos) {
+            technologyRouteChildInfo.setRouteCode(bsTechnologyRouteInfo.getRouteCode());
+            int i1 = bsTechnologyRouteChildInfoMapper.updateBsTechnologyRouteChildByCodeInfo(technologyRouteChildInfo);
+        }
+        return i;
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/technologyRouteChild/controller/BsTechnologyRouteChildInfoController.java b/jcdm-main/src/main/java/com/jcdm/main/bs/technologyRouteChild/controller/BsTechnologyRouteChildInfoController.java
new file mode 100644
index 0000000..d96bbfc
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/technologyRouteChild/controller/BsTechnologyRouteChildInfoController.java
@@ -0,0 +1,104 @@
+package com.jcdm.main.bs.controller;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.main.bs.domain.BsTechnologyRouteChildInfo;
+import com.jcdm.main.bs.service.IBsTechnologyRouteChildInfoService;
+import com.jcdm.common.utils.poi.ExcelUtil;
+import com.jcdm.common.core.page.TableDataInfo;
+
+/**
+ * 宸ヨ壓璺嚎瀛愪俊鎭疌ontroller
+ * 
+ * @author ruimin
+ * @date 2023-12-09
+ */
+@RestController
+@RequestMapping("/bs/technologyRouteChild")
+public class BsTechnologyRouteChildInfoController extends BaseController
+{
+    @Autowired
+    private IBsTechnologyRouteChildInfoService bsTechnologyRouteChildInfoService;
+
+    /**
+     * 鏌ヨ宸ヨ壓璺嚎瀛愪俊鎭垪琛�
+     */
+    @PreAuthorize("@ss.hasPermi('bs:technologyRouteChild:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(BsTechnologyRouteChildInfo bsTechnologyRouteChildInfo)
+    {
+        startPage();
+        List<BsTechnologyRouteChildInfo> list = bsTechnologyRouteChildInfoService.selectBsTechnologyRouteChildInfoList(bsTechnologyRouteChildInfo);
+        return getDataTable(list);
+    }
+
+    /**
+     * 瀵煎嚭宸ヨ壓璺嚎瀛愪俊鎭垪琛�
+     */
+    @PreAuthorize("@ss.hasPermi('bs:technologyRouteChild:export')")
+    @Log(title = "宸ヨ壓璺嚎瀛愪俊鎭�", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, BsTechnologyRouteChildInfo bsTechnologyRouteChildInfo)
+    {
+        List<BsTechnologyRouteChildInfo> list = bsTechnologyRouteChildInfoService.selectBsTechnologyRouteChildInfoList(bsTechnologyRouteChildInfo);
+        ExcelUtil<BsTechnologyRouteChildInfo> util = new ExcelUtil<BsTechnologyRouteChildInfo>(BsTechnologyRouteChildInfo.class);
+        util.exportExcel(response, list, "宸ヨ壓璺嚎瀛愪俊鎭暟鎹�");
+    }
+
+    /**
+     * 鑾峰彇宸ヨ壓璺嚎瀛愪俊鎭缁嗕俊鎭�
+     */
+    @PreAuthorize("@ss.hasPermi('bs:technologyRouteChild:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(bsTechnologyRouteChildInfoService.selectBsTechnologyRouteChildInfoById(id));
+    }
+
+    /**
+     * 鏂板宸ヨ壓璺嚎瀛愪俊鎭�
+     */
+    @PreAuthorize("@ss.hasPermi('bs:technologyRouteChild:add')")
+    @Log(title = "宸ヨ壓璺嚎瀛愪俊鎭�", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody BsTechnologyRouteChildInfo bsTechnologyRouteChildInfo)
+    {
+        return toAjax(bsTechnologyRouteChildInfoService.insertBsTechnologyRouteChildInfo(bsTechnologyRouteChildInfo));
+    }
+
+    /**
+     * 淇敼宸ヨ壓璺嚎瀛愪俊鎭�
+     */
+    @PreAuthorize("@ss.hasPermi('bs:technologyRouteChild:edit')")
+    @Log(title = "宸ヨ壓璺嚎瀛愪俊鎭�", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody BsTechnologyRouteChildInfo bsTechnologyRouteChildInfo)
+    {
+        return toAjax(bsTechnologyRouteChildInfoService.updateBsTechnologyRouteChildInfo(bsTechnologyRouteChildInfo));
+    }
+
+    /**
+     * 鍒犻櫎宸ヨ壓璺嚎瀛愪俊鎭�
+     */
+    @PreAuthorize("@ss.hasPermi('bs:technologyRouteChild:remove')")
+    @Log(title = "宸ヨ壓璺嚎瀛愪俊鎭�", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(bsTechnologyRouteChildInfoService.deleteBsTechnologyRouteChildInfoByIds(ids));
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/technologyRouteChild/domain/BsTechnologyRouteChildInfo.java b/jcdm-main/src/main/java/com/jcdm/main/bs/technologyRouteChild/domain/BsTechnologyRouteChildInfo.java
new file mode 100644
index 0000000..f30e6ef
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/technologyRouteChild/domain/BsTechnologyRouteChildInfo.java
@@ -0,0 +1,257 @@
+package com.jcdm.main.bs.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.core.domain.BaseEntity;
+
+/**
+ * 宸ヨ壓璺嚎瀛愪俊鎭璞� bs_technology_route_child_info
+ * 
+ * @author ruimin
+ * @date 2023-12-09
+ */
+public class BsTechnologyRouteChildInfo extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 涓婚敭id */
+    private Long id;
+
+    /** 宸ュ簭缂栫爜 */
+    @Excel(name = "宸ュ簭缂栫爜")
+    private String processesCode;
+
+    /** 宸ュ簭鍚嶇О */
+    @Excel(name = "宸ュ簭鍚嶇О")
+    private String processesName;
+
+    /** 鍔犲伐椤哄簭 */
+    @Excel(name = "鍔犲伐椤哄簭")
+    private String stepNo;
+
+    /** 涓嬩竴閬撳伐搴� */
+    @Excel(name = "涓嬩竴閬撳伐搴�")
+    private String nextProcess;
+
+    /** 涓庝笅涓�閬撳伐搴忓叧绯� */
+    @Excel(name = "涓庝笅涓�閬撳伐搴忓叧绯�")
+    private String nextProcessBond;
+
+    /** 鏄惁鍏抽敭宸ュ簭 */
+    @Excel(name = "鏄惁鍏抽敭宸ュ簭")
+    private String keyProcessesFlag;
+
+    /** 鍑嗗鏃堕棿 */
+    @Excel(name = "鍑嗗鏃堕棿")
+    private String preparationTime;
+
+    /** 绛夊緟鏃堕棿 */
+    @Excel(name = "绛夊緟鏃堕棿")
+    private String waitTime;
+
+    /** 鍒涘缓鐢ㄦ埛 */
+    @Excel(name = "鍒涘缓鐢ㄦ埛")
+    private String createUser;
+
+    /** 鏇存敼鐢ㄦ埛 */
+    @Excel(name = "鏇存敼鐢ㄦ埛")
+    private String updateUser;
+
+    /** 宸ヨ壓娴佺▼缂栫爜 */
+    @Excel(name = "宸ヨ壓娴佺▼缂栫爜")
+    private String routeCode;
+
+    /** 棰勭暀瀛楁1 */
+    private String spareField1;
+
+    /** 棰勭暀瀛楁2 */
+    private String spareField2;
+
+    /** 棰勭暀瀛楁3 */
+    private String spareField3;
+
+    /** 棰勭暀瀛楁4 */
+    private String spareField4;
+
+    /** 宸ヨ壓娴佺▼ID */
+    private Long routeId;
+
+    public void setId(Long id) 
+    {
+        this.id = id;
+    }
+
+    public Long getId() 
+    {
+        return id;
+    }
+    public void setProcessesCode(String processesCode) 
+    {
+        this.processesCode = processesCode;
+    }
+
+    public String getProcessesCode() 
+    {
+        return processesCode;
+    }
+    public void setProcessesName(String processesName) 
+    {
+        this.processesName = processesName;
+    }
+
+    public String getProcessesName() 
+    {
+        return processesName;
+    }
+    public void setStepNo(String stepNo) 
+    {
+        this.stepNo = stepNo;
+    }
+
+    public String getStepNo() 
+    {
+        return stepNo;
+    }
+    public void setNextProcess(String nextProcess) 
+    {
+        this.nextProcess = nextProcess;
+    }
+
+    public String getNextProcess() 
+    {
+        return nextProcess;
+    }
+    public void setNextProcessBond(String nextProcessBond) 
+    {
+        this.nextProcessBond = nextProcessBond;
+    }
+
+    public String getNextProcessBond() 
+    {
+        return nextProcessBond;
+    }
+    public void setKeyProcessesFlag(String keyProcessesFlag) 
+    {
+        this.keyProcessesFlag = keyProcessesFlag;
+    }
+
+    public String getKeyProcessesFlag() 
+    {
+        return keyProcessesFlag;
+    }
+    public void setPreparationTime(String preparationTime) 
+    {
+        this.preparationTime = preparationTime;
+    }
+
+    public String getPreparationTime() 
+    {
+        return preparationTime;
+    }
+    public void setWaitTime(String waitTime) 
+    {
+        this.waitTime = waitTime;
+    }
+
+    public String getWaitTime() 
+    {
+        return waitTime;
+    }
+    public void setCreateUser(String createUser) 
+    {
+        this.createUser = createUser;
+    }
+
+    public String getCreateUser() 
+    {
+        return createUser;
+    }
+    public void setUpdateUser(String updateUser) 
+    {
+        this.updateUser = updateUser;
+    }
+
+    public String getUpdateUser() 
+    {
+        return updateUser;
+    }
+    public void setRouteCode(String routeCode) 
+    {
+        this.routeCode = routeCode;
+    }
+
+    public String getRouteCode() 
+    {
+        return routeCode;
+    }
+    public void setSpareField1(String spareField1) 
+    {
+        this.spareField1 = spareField1;
+    }
+
+    public String getSpareField1() 
+    {
+        return spareField1;
+    }
+    public void setSpareField2(String spareField2) 
+    {
+        this.spareField2 = spareField2;
+    }
+
+    public String getSpareField2() 
+    {
+        return spareField2;
+    }
+    public void setSpareField3(String spareField3) 
+    {
+        this.spareField3 = spareField3;
+    }
+
+    public String getSpareField3() 
+    {
+        return spareField3;
+    }
+    public void setSpareField4(String spareField4) 
+    {
+        this.spareField4 = spareField4;
+    }
+
+    public String getSpareField4() 
+    {
+        return spareField4;
+    }
+
+    public Long getRouteId() {
+        return routeId;
+    }
+
+    public void setRouteId(Long routeId) {
+        this.routeId = routeId;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("processesCode", getProcessesCode())
+            .append("processesName", getProcessesName())
+            .append("stepNo", getStepNo())
+            .append("nextProcess", getNextProcess())
+            .append("nextProcessBond", getNextProcessBond())
+            .append("keyProcessesFlag", getKeyProcessesFlag())
+            .append("preparationTime", getPreparationTime())
+            .append("waitTime", getWaitTime())
+            .append("createUser", getCreateUser())
+            .append("createTime", getCreateTime())
+            .append("updateUser", getUpdateUser())
+            .append("updateTime", getUpdateTime())
+            .append("remark", getRemark())
+            .append("routeCode", getRouteCode())
+            .append("spareField1", getSpareField1())
+            .append("spareField2", getSpareField2())
+            .append("spareField3", getSpareField3())
+            .append("spareField4", getSpareField4())
+            .toString();
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/technologyRouteChild/mapper/BsTechnologyRouteChildInfoMapper.java b/jcdm-main/src/main/java/com/jcdm/main/bs/technologyRouteChild/mapper/BsTechnologyRouteChildInfoMapper.java
new file mode 100644
index 0000000..fc09dd9
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/technologyRouteChild/mapper/BsTechnologyRouteChildInfoMapper.java
@@ -0,0 +1,64 @@
+package com.jcdm.main.bs.mapper;
+
+import java.util.List;
+import com.jcdm.main.bs.domain.BsTechnologyRouteChildInfo;
+
+/**
+ * 宸ヨ壓璺嚎瀛愪俊鎭疢apper鎺ュ彛
+ * 
+ * @author ruimin
+ * @date 2023-12-09
+ */
+public interface BsTechnologyRouteChildInfoMapper 
+{
+    /**
+     * 鏌ヨ宸ヨ壓璺嚎瀛愪俊鎭�
+     * 
+     * @param id 宸ヨ壓璺嚎瀛愪俊鎭富閿�
+     * @return 宸ヨ壓璺嚎瀛愪俊鎭�
+     */
+    public BsTechnologyRouteChildInfo selectBsTechnologyRouteChildInfoById(Long id);
+
+    /**
+     * 鏌ヨ宸ヨ壓璺嚎瀛愪俊鎭垪琛�
+     * 
+     * @param bsTechnologyRouteChildInfo 宸ヨ壓璺嚎瀛愪俊鎭�
+     * @return 宸ヨ壓璺嚎瀛愪俊鎭泦鍚�
+     */
+    public List<BsTechnologyRouteChildInfo> selectBsTechnologyRouteChildInfoList(BsTechnologyRouteChildInfo bsTechnologyRouteChildInfo);
+
+    /**
+     * 鏂板宸ヨ壓璺嚎瀛愪俊鎭�
+     * 
+     * @param bsTechnologyRouteChildInfo 宸ヨ壓璺嚎瀛愪俊鎭�
+     * @return 缁撴灉
+     */
+    public int insertBsTechnologyRouteChildInfo(BsTechnologyRouteChildInfo bsTechnologyRouteChildInfo);
+
+    /**
+     * 淇敼宸ヨ壓璺嚎瀛愪俊鎭�
+     * 
+     * @param bsTechnologyRouteChildInfo 宸ヨ壓璺嚎瀛愪俊鎭�
+     * @return 缁撴灉
+     */
+    public int updateBsTechnologyRouteChildInfo(BsTechnologyRouteChildInfo bsTechnologyRouteChildInfo);
+
+    public int updateBsTechnologyRouteChildByCodeInfo(BsTechnologyRouteChildInfo bsTechnologyRouteChildInfo);
+
+
+    /**
+     * 鍒犻櫎宸ヨ壓璺嚎瀛愪俊鎭�
+     * 
+     * @param id 宸ヨ壓璺嚎瀛愪俊鎭富閿�
+     * @return 缁撴灉
+     */
+    public int deleteBsTechnologyRouteChildInfoById(Long id);
+
+    /**
+     * 鎵归噺鍒犻櫎宸ヨ壓璺嚎瀛愪俊鎭�
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteBsTechnologyRouteChildInfoByIds(Long[] ids);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/technologyRouteChild/service/IBsTechnologyRouteChildInfoService.java b/jcdm-main/src/main/java/com/jcdm/main/bs/technologyRouteChild/service/IBsTechnologyRouteChildInfoService.java
new file mode 100644
index 0000000..ee3c274
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/technologyRouteChild/service/IBsTechnologyRouteChildInfoService.java
@@ -0,0 +1,61 @@
+package com.jcdm.main.bs.service;
+
+import java.util.List;
+import com.jcdm.main.bs.domain.BsTechnologyRouteChildInfo;
+
+/**
+ * 宸ヨ壓璺嚎瀛愪俊鎭疭ervice鎺ュ彛
+ * 
+ * @author ruimin
+ * @date 2023-12-09
+ */
+public interface IBsTechnologyRouteChildInfoService 
+{
+    /**
+     * 鏌ヨ宸ヨ壓璺嚎瀛愪俊鎭�
+     * 
+     * @param id 宸ヨ壓璺嚎瀛愪俊鎭富閿�
+     * @return 宸ヨ壓璺嚎瀛愪俊鎭�
+     */
+    public BsTechnologyRouteChildInfo selectBsTechnologyRouteChildInfoById(Long id);
+
+    /**
+     * 鏌ヨ宸ヨ壓璺嚎瀛愪俊鎭垪琛�
+     * 
+     * @param bsTechnologyRouteChildInfo 宸ヨ壓璺嚎瀛愪俊鎭�
+     * @return 宸ヨ壓璺嚎瀛愪俊鎭泦鍚�
+     */
+    public List<BsTechnologyRouteChildInfo> selectBsTechnologyRouteChildInfoList(BsTechnologyRouteChildInfo bsTechnologyRouteChildInfo);
+
+    /**
+     * 鏂板宸ヨ壓璺嚎瀛愪俊鎭�
+     * 
+     * @param bsTechnologyRouteChildInfo 宸ヨ壓璺嚎瀛愪俊鎭�
+     * @return 缁撴灉
+     */
+    public int insertBsTechnologyRouteChildInfo(BsTechnologyRouteChildInfo bsTechnologyRouteChildInfo);
+
+    /**
+     * 淇敼宸ヨ壓璺嚎瀛愪俊鎭�
+     * 
+     * @param bsTechnologyRouteChildInfo 宸ヨ壓璺嚎瀛愪俊鎭�
+     * @return 缁撴灉
+     */
+    public int updateBsTechnologyRouteChildInfo(BsTechnologyRouteChildInfo bsTechnologyRouteChildInfo);
+
+    /**
+     * 鎵归噺鍒犻櫎宸ヨ壓璺嚎瀛愪俊鎭�
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑宸ヨ壓璺嚎瀛愪俊鎭富閿泦鍚�
+     * @return 缁撴灉
+     */
+    public int deleteBsTechnologyRouteChildInfoByIds(Long[] ids);
+
+    /**
+     * 鍒犻櫎宸ヨ壓璺嚎瀛愪俊鎭俊鎭�
+     * 
+     * @param id 宸ヨ壓璺嚎瀛愪俊鎭富閿�
+     * @return 缁撴灉
+     */
+    public int deleteBsTechnologyRouteChildInfoById(Long id);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/technologyRouteChild/service/impl/BsTechnologyRouteChildInfoServiceImpl.java b/jcdm-main/src/main/java/com/jcdm/main/bs/technologyRouteChild/service/impl/BsTechnologyRouteChildInfoServiceImpl.java
new file mode 100644
index 0000000..25a5783
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/technologyRouteChild/service/impl/BsTechnologyRouteChildInfoServiceImpl.java
@@ -0,0 +1,100 @@
+package com.jcdm.main.bs.service.impl;
+
+import java.util.List;
+import com.jcdm.common.utils.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.jcdm.main.bs.mapper.BsTechnologyRouteChildInfoMapper;
+import com.jcdm.main.bs.domain.BsTechnologyRouteChildInfo;
+import com.jcdm.main.bs.service.IBsTechnologyRouteChildInfoService;
+
+import static org.apache.commons.lang3.SystemUtils.getUserName;
+
+/**
+ * 宸ヨ壓璺嚎瀛愪俊鎭疭ervice涓氬姟灞傚鐞�
+ * 
+ * @author ruimin
+ * @date 2023-12-09
+ */
+@Service
+public class BsTechnologyRouteChildInfoServiceImpl implements IBsTechnologyRouteChildInfoService 
+{
+    @Autowired
+    private BsTechnologyRouteChildInfoMapper bsTechnologyRouteChildInfoMapper;
+
+    /**
+     * 鏌ヨ宸ヨ壓璺嚎瀛愪俊鎭�
+     * 
+     * @param id 宸ヨ壓璺嚎瀛愪俊鎭富閿�
+     * @return 宸ヨ壓璺嚎瀛愪俊鎭�
+     */
+    @Override
+    public BsTechnologyRouteChildInfo selectBsTechnologyRouteChildInfoById(Long id)
+    {
+        return bsTechnologyRouteChildInfoMapper.selectBsTechnologyRouteChildInfoById(id);
+    }
+
+    /**
+     * 鏌ヨ宸ヨ壓璺嚎瀛愪俊鎭垪琛�
+     * 
+     * @param bsTechnologyRouteChildInfo 宸ヨ壓璺嚎瀛愪俊鎭�
+     * @return 宸ヨ壓璺嚎瀛愪俊鎭�
+     */
+    @Override
+    public List<BsTechnologyRouteChildInfo> selectBsTechnologyRouteChildInfoList(BsTechnologyRouteChildInfo bsTechnologyRouteChildInfo)
+    {
+        return bsTechnologyRouteChildInfoMapper.selectBsTechnologyRouteChildInfoList(bsTechnologyRouteChildInfo);
+    }
+
+    /**
+     * 鏂板宸ヨ壓璺嚎瀛愪俊鎭�
+     * 
+     * @param bsTechnologyRouteChildInfo 宸ヨ壓璺嚎瀛愪俊鎭�
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertBsTechnologyRouteChildInfo(BsTechnologyRouteChildInfo bsTechnologyRouteChildInfo)
+    {
+        bsTechnologyRouteChildInfo.setCreateTime(DateUtils.getNowDate());
+        bsTechnologyRouteChildInfo.setCreateUser(getUserName());
+        return bsTechnologyRouteChildInfoMapper.insertBsTechnologyRouteChildInfo(bsTechnologyRouteChildInfo);
+    }
+
+    /**
+     * 淇敼宸ヨ壓璺嚎瀛愪俊鎭�
+     * 
+     * @param bsTechnologyRouteChildInfo 宸ヨ壓璺嚎瀛愪俊鎭�
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateBsTechnologyRouteChildInfo(BsTechnologyRouteChildInfo bsTechnologyRouteChildInfo)
+    {
+        bsTechnologyRouteChildInfo.setUpdateTime(DateUtils.getNowDate());
+        bsTechnologyRouteChildInfo.setUpdateUser(getUserName());
+        return bsTechnologyRouteChildInfoMapper.updateBsTechnologyRouteChildInfo(bsTechnologyRouteChildInfo);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎宸ヨ壓璺嚎瀛愪俊鎭�
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑宸ヨ壓璺嚎瀛愪俊鎭富閿�
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteBsTechnologyRouteChildInfoByIds(Long[] ids)
+    {
+        return bsTechnologyRouteChildInfoMapper.deleteBsTechnologyRouteChildInfoByIds(ids);
+    }
+
+    /**
+     * 鍒犻櫎宸ヨ壓璺嚎瀛愪俊鎭俊鎭�
+     * 
+     * @param id 宸ヨ壓璺嚎瀛愪俊鎭富閿�
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteBsTechnologyRouteChildInfoById(Long id)
+    {
+        return bsTechnologyRouteChildInfoMapper.deleteBsTechnologyRouteChildInfoById(id);
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/workshop/controller/BsWorkshopInfoController.java b/jcdm-main/src/main/java/com/jcdm/main/bs/workshop/controller/BsWorkshopInfoController.java
new file mode 100644
index 0000000..fed473f
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/workshop/controller/BsWorkshopInfoController.java
@@ -0,0 +1,105 @@
+package com.jcdm.main.bs.workshop.controller;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.jcdm.main.bs.workshop.service.IBsWorkshopInfoService;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.main.bs.workshop.domain.BsWorkshopInfo;
+import com.jcdm.common.utils.poi.ExcelUtil;
+import com.jcdm.common.core.page.TableDataInfo;
+
+/**
+ * 杞﹂棿淇℃伅Controller
+ * 
+ * @author jc
+ * @date 2023-12-06
+ */
+@RestController
+@RequestMapping("/bs/workshop")
+public class BsWorkshopInfoController extends BaseController
+{
+    @Autowired
+    private IBsWorkshopInfoService bsWorkshopInfoService;
+
+    /**
+     * 鏌ヨ杞﹂棿淇℃伅鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('bs:workshop:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(BsWorkshopInfo bsWorkshopInfo)
+    {
+        startPage();
+        List<BsWorkshopInfo> list = bsWorkshopInfoService.selectBsWorkshopInfoList(bsWorkshopInfo);
+        return getDataTable(list);
+    }
+
+    /**
+     * 瀵煎嚭杞﹂棿淇℃伅鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('bs:workshop:export')")
+    @Log(title = "杞﹂棿淇℃伅", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, BsWorkshopInfo bsWorkshopInfo)
+    {
+        List<BsWorkshopInfo> list = bsWorkshopInfoService.selectBsWorkshopInfoList(bsWorkshopInfo);
+        ExcelUtil<BsWorkshopInfo> util = new ExcelUtil<BsWorkshopInfo>(BsWorkshopInfo.class);
+        util.exportExcel(response, list, "杞﹂棿淇℃伅鏁版嵁");
+    }
+
+    /**
+     * 鑾峰彇杞﹂棿淇℃伅璇︾粏淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('bs:workshop:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(bsWorkshopInfoService.selectBsWorkshopInfoById(id));
+    }
+
+    /**
+     * 鏂板杞﹂棿淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('bs:workshop:add')")
+    @Log(title = "杞﹂棿淇℃伅", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody BsWorkshopInfo bsWorkshopInfo)
+    {
+        return toAjax(bsWorkshopInfoService.insertBsWorkshopInfo(bsWorkshopInfo));
+    }
+
+    /**
+     * 淇敼杞﹂棿淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('bs:workshop:edit')")
+    @Log(title = "杞﹂棿淇℃伅", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody BsWorkshopInfo bsWorkshopInfo)
+    {
+        return toAjax(bsWorkshopInfoService.updateBsWorkshopInfo(bsWorkshopInfo));
+    }
+
+    /**
+     * 鍒犻櫎杞﹂棿淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('bs:workshop:remove')")
+    @Log(title = "杞﹂棿淇℃伅", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(bsWorkshopInfoService.deleteBsWorkshopInfoByIds(ids));
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/workshop/domain/BsWorkshopInfo.java b/jcdm-main/src/main/java/com/jcdm/main/bs/workshop/domain/BsWorkshopInfo.java
new file mode 100644
index 0000000..8f27964
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/workshop/domain/BsWorkshopInfo.java
@@ -0,0 +1,144 @@
+package com.jcdm.main.bs.workshop.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.core.domain.BaseEntity;
+
+/**
+ * 杞﹂棿淇℃伅瀵硅薄 bs_workshop_info
+ * 
+ * @author jc
+ * @date 2023-12-06
+ */
+public class BsWorkshopInfo extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** id */
+    private Long id;
+
+    /** 杞﹂棿缂栫爜 */
+    @Excel(name = "杞﹂棿缂栫爜")
+    private String workshopCode;
+
+    /** 杞﹂棿鍚嶇О */
+    @Excel(name = "杞﹂棿鍚嶇О")
+    private String workshopName;
+
+    /** 澶囩敤瀛楁1 */
+    private String spareField1;
+
+    /** 澶囩敤瀛楁2 */
+    private String spareField2;
+
+    /** 澶囨敞 */
+    @Excel(name = "澶囨敞")
+    private String remarks;
+
+    /** 鍒涘缓浜� */
+    @Excel(name = "鍒涘缓浜�")
+    private String createUser;
+
+    /** 鏇存柊浜� */
+    @Excel(name = "鏇存柊浜�")
+    private String updateUser;
+
+    @Excel(name = "鐘舵��")
+    private String status;
+
+    public void setId(Long id) 
+    {
+        this.id = id;
+    }
+
+    public Long getId() 
+    {
+        return id;
+    }
+    public void setWorkshopCode(String workshopCode) 
+    {
+        this.workshopCode = workshopCode;
+    }
+
+    public String getWorkshopCode() 
+    {
+        return workshopCode;
+    }
+    public void setWorkshopName(String workshopName) 
+    {
+        this.workshopName = workshopName;
+    }
+
+    public String getWorkshopName() 
+    {
+        return workshopName;
+    }
+    public void setSpareField1(String spareField1) 
+    {
+        this.spareField1 = spareField1;
+    }
+
+    public String getSpareField1() 
+    {
+        return spareField1;
+    }
+    public void setSpareField2(String spareField2) 
+    {
+        this.spareField2 = spareField2;
+    }
+
+    public String getSpareField2() 
+    {
+        return spareField2;
+    }
+    public void setStatus(String status)
+    {
+        this.status = status;
+    }
+    public String getStatus() {return status;}
+    public void setRemarks(String remarks) 
+    {
+        this.remarks = remarks;
+    }
+
+    public String getRemarks() 
+    {
+        return remarks;
+    }
+    public void setCreateUser(String createUser) 
+    {
+        this.createUser = createUser;
+    }
+
+    public String getCreateUser() 
+    {
+        return createUser;
+    }
+    public void setUpdateUser(String updateUser) 
+    {
+        this.updateUser = updateUser;
+    }
+
+    public String getUpdateUser() 
+    {
+        return updateUser;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("workshopCode", getWorkshopCode())
+            .append("workshopName", getWorkshopName())
+            .append("spareField1", getSpareField1())
+            .append("spareField2", getSpareField2())
+            .append("remarks", getRemarks())
+            .append("createUser", getCreateUser())
+            .append("createTime", getCreateTime())
+            .append("updateUser", getUpdateUser())
+            .append("updateTime", getUpdateTime())
+            .append("status", getStatus())
+            .toString();
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/workshop/mapper/BsWorkshopInfoMapper.java b/jcdm-main/src/main/java/com/jcdm/main/bs/workshop/mapper/BsWorkshopInfoMapper.java
new file mode 100644
index 0000000..a840d42
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/workshop/mapper/BsWorkshopInfoMapper.java
@@ -0,0 +1,61 @@
+package com.jcdm.main.bs.workshop.mapper;
+
+import java.util.List;
+import com.jcdm.main.bs.workshop.domain.BsWorkshopInfo;
+
+/**
+ * 杞﹂棿淇℃伅Mapper鎺ュ彛
+ * 
+ * @author jc
+ * @date 2023-12-06
+ */
+public interface BsWorkshopInfoMapper 
+{
+    /**
+     * 鏌ヨ杞﹂棿淇℃伅
+     * 
+     * @param id 杞﹂棿淇℃伅涓婚敭
+     * @return 杞﹂棿淇℃伅
+     */
+    public BsWorkshopInfo selectBsWorkshopInfoById(Long id);
+
+    /**
+     * 鏌ヨ杞﹂棿淇℃伅鍒楄〃
+     * 
+     * @param bsWorkshopInfo 杞﹂棿淇℃伅
+     * @return 杞﹂棿淇℃伅闆嗗悎
+     */
+    public List<BsWorkshopInfo> selectBsWorkshopInfoList(BsWorkshopInfo bsWorkshopInfo);
+
+    /**
+     * 鏂板杞﹂棿淇℃伅
+     * 
+     * @param bsWorkshopInfo 杞﹂棿淇℃伅
+     * @return 缁撴灉
+     */
+    public int insertBsWorkshopInfo(BsWorkshopInfo bsWorkshopInfo);
+
+    /**
+     * 淇敼杞﹂棿淇℃伅
+     * 
+     * @param bsWorkshopInfo 杞﹂棿淇℃伅
+     * @return 缁撴灉
+     */
+    public int updateBsWorkshopInfo(BsWorkshopInfo bsWorkshopInfo);
+
+    /**
+     * 鍒犻櫎杞﹂棿淇℃伅
+     * 
+     * @param id 杞﹂棿淇℃伅涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteBsWorkshopInfoById(Long id);
+
+    /**
+     * 鎵归噺鍒犻櫎杞﹂棿淇℃伅
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteBsWorkshopInfoByIds(Long[] ids);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/workshop/service/IBsWorkshopInfoService.java b/jcdm-main/src/main/java/com/jcdm/main/bs/workshop/service/IBsWorkshopInfoService.java
new file mode 100644
index 0000000..11a57da
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/workshop/service/IBsWorkshopInfoService.java
@@ -0,0 +1,61 @@
+package com.jcdm.main.bs.workshop.service;
+
+import java.util.List;
+import com.jcdm.main.bs.workshop.domain.BsWorkshopInfo;
+
+/**
+ * 杞﹂棿淇℃伅Service鎺ュ彛
+ * 
+ * @author jc
+ * @date 2023-12-06
+ */
+public interface IBsWorkshopInfoService 
+{
+    /**
+     * 鏌ヨ杞﹂棿淇℃伅
+     * 
+     * @param id 杞﹂棿淇℃伅涓婚敭
+     * @return 杞﹂棿淇℃伅
+     */
+    public BsWorkshopInfo selectBsWorkshopInfoById(Long id);
+
+    /**
+     * 鏌ヨ杞﹂棿淇℃伅鍒楄〃
+     * 
+     * @param bsWorkshopInfo 杞﹂棿淇℃伅
+     * @return 杞﹂棿淇℃伅闆嗗悎
+     */
+    public List<BsWorkshopInfo> selectBsWorkshopInfoList(BsWorkshopInfo bsWorkshopInfo);
+
+    /**
+     * 鏂板杞﹂棿淇℃伅
+     * 
+     * @param bsWorkshopInfo 杞﹂棿淇℃伅
+     * @return 缁撴灉
+     */
+    public int insertBsWorkshopInfo(BsWorkshopInfo bsWorkshopInfo);
+
+    /**
+     * 淇敼杞﹂棿淇℃伅
+     * 
+     * @param bsWorkshopInfo 杞﹂棿淇℃伅
+     * @return 缁撴灉
+     */
+    public int updateBsWorkshopInfo(BsWorkshopInfo bsWorkshopInfo);
+
+    /**
+     * 鎵归噺鍒犻櫎杞﹂棿淇℃伅
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑杞﹂棿淇℃伅涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteBsWorkshopInfoByIds(Long[] ids);
+
+    /**
+     * 鍒犻櫎杞﹂棿淇℃伅淇℃伅
+     * 
+     * @param id 杞﹂棿淇℃伅涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteBsWorkshopInfoById(Long id);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/bs/workshop/service/impl/BsWorkshopInfoServiceImpl.java b/jcdm-main/src/main/java/com/jcdm/main/bs/workshop/service/impl/BsWorkshopInfoServiceImpl.java
new file mode 100644
index 0000000..00bc99a
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/bs/workshop/service/impl/BsWorkshopInfoServiceImpl.java
@@ -0,0 +1,100 @@
+package com.jcdm.main.bs.workshop.service.impl;
+
+import java.util.List;
+import com.jcdm.common.utils.DateUtils;
+import com.jcdm.main.bs.workshop.service.IBsWorkshopInfoService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.jcdm.main.bs.workshop.mapper.BsWorkshopInfoMapper;
+import com.jcdm.main.bs.workshop.domain.BsWorkshopInfo;
+
+import static org.apache.commons.lang3.SystemUtils.getUserName;
+
+/**
+ * 杞﹂棿淇℃伅Service涓氬姟灞傚鐞�
+ * 
+ * @author jc
+ * @date 2023-12-06
+ */
+@Service
+public class BsWorkshopInfoServiceImpl implements IBsWorkshopInfoService
+{
+    @Autowired
+    private BsWorkshopInfoMapper bsWorkshopInfoMapper;
+
+    /**
+     * 鏌ヨ杞﹂棿淇℃伅
+     * 
+     * @param id 杞﹂棿淇℃伅涓婚敭
+     * @return 杞﹂棿淇℃伅
+     */
+    @Override
+    public BsWorkshopInfo selectBsWorkshopInfoById(Long id)
+    {
+        return bsWorkshopInfoMapper.selectBsWorkshopInfoById(id);
+    }
+
+    /**
+     * 鏌ヨ杞﹂棿淇℃伅鍒楄〃
+     * 
+     * @param bsWorkshopInfo 杞﹂棿淇℃伅
+     * @return 杞﹂棿淇℃伅
+     */
+    @Override
+    public List<BsWorkshopInfo> selectBsWorkshopInfoList(BsWorkshopInfo bsWorkshopInfo)
+    {
+        return bsWorkshopInfoMapper.selectBsWorkshopInfoList(bsWorkshopInfo);
+    }
+
+    /**
+     * 鏂板杞﹂棿淇℃伅
+     * 
+     * @param bsWorkshopInfo 杞﹂棿淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertBsWorkshopInfo(BsWorkshopInfo bsWorkshopInfo)
+    {
+        bsWorkshopInfo.setCreateTime(DateUtils.getNowDate());
+        bsWorkshopInfo.setCreateUser(getUserName());
+        return bsWorkshopInfoMapper.insertBsWorkshopInfo(bsWorkshopInfo);
+    }
+
+    /**
+     * 淇敼杞﹂棿淇℃伅
+     * 
+     * @param bsWorkshopInfo 杞﹂棿淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateBsWorkshopInfo(BsWorkshopInfo bsWorkshopInfo)
+    {
+        bsWorkshopInfo.setUpdateTime(DateUtils.getNowDate());
+        bsWorkshopInfo.setUpdateUser(getUserName());
+        return bsWorkshopInfoMapper.updateBsWorkshopInfo(bsWorkshopInfo);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎杞﹂棿淇℃伅
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑杞﹂棿淇℃伅涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteBsWorkshopInfoByIds(Long[] ids)
+    {
+        return bsWorkshopInfoMapper.deleteBsWorkshopInfoByIds(ids);
+    }
+
+    /**
+     * 鍒犻櫎杞﹂棿淇℃伅淇℃伅
+     * 
+     * @param id 杞﹂棿淇℃伅涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteBsWorkshopInfoById(Long id)
+    {
+        return bsWorkshopInfoMapper.deleteBsWorkshopInfoById(id);
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/da/collectionParamConf/controller/DaCollectionParamConfController.java b/jcdm-main/src/main/java/com/jcdm/main/da/collectionParamConf/controller/DaCollectionParamConfController.java
new file mode 100644
index 0000000..93dc5c6
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/da/collectionParamConf/controller/DaCollectionParamConfController.java
@@ -0,0 +1,98 @@
+package com.jcdm.main.da.collectionParamConf.controller;
+
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.core.page.TableDataInfo;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.common.utils.poi.ExcelUtil;
+import com.jcdm.main.da.collectionParamConf.domain.DaCollectionParamConf;
+import com.jcdm.main.da.collectionParamConf.service.IDaCollectionParamConfService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+
+/**
+ * 閲囬泦鍙傛暟閰嶇疆Controller
+ * 
+ * @author ruimin
+ * @date 2023-12-25
+ */
+@RestController
+@RequestMapping("/da/collectionParamConf")
+public class DaCollectionParamConfController extends BaseController
+{
+    @Autowired
+    private IDaCollectionParamConfService daCollectionParamConfService;
+
+    /**
+     * 鏌ヨ閲囬泦鍙傛暟閰嶇疆鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('da:collectionParamConf:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(DaCollectionParamConf daCollectionParamConf)
+    {
+        startPage();
+        List<DaCollectionParamConf> list = daCollectionParamConfService.selectDaCollectionParamConfList(daCollectionParamConf);
+        return getDataTable(list);
+    }
+
+    /**
+     * 瀵煎嚭閲囬泦鍙傛暟閰嶇疆鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('da:collectionParamConf:export')")
+    @Log(title = "閲囬泦鍙傛暟閰嶇疆", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, DaCollectionParamConf daCollectionParamConf)
+    {
+        List<DaCollectionParamConf> list = daCollectionParamConfService.selectDaCollectionParamConfList(daCollectionParamConf);
+        ExcelUtil<DaCollectionParamConf> util = new ExcelUtil<DaCollectionParamConf>(DaCollectionParamConf.class);
+        util.exportExcel(response, list, "閲囬泦鍙傛暟閰嶇疆鏁版嵁");
+    }
+
+    /**
+     * 鑾峰彇閲囬泦鍙傛暟閰嶇疆璇︾粏淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('da:collectionParamConf:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(daCollectionParamConfService.selectDaCollectionParamConfById(id));
+    }
+
+    /**
+     * 鏂板閲囬泦鍙傛暟閰嶇疆
+     */
+    @PreAuthorize("@ss.hasPermi('da:collectionParamConf:add')")
+    @Log(title = "閲囬泦鍙傛暟閰嶇疆", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody DaCollectionParamConf daCollectionParamConf)
+    {
+        return toAjax(daCollectionParamConfService.insertDaCollectionParamConf(daCollectionParamConf));
+    }
+
+    /**
+     * 淇敼閲囬泦鍙傛暟閰嶇疆
+     */
+    @PreAuthorize("@ss.hasPermi('da:collectionParamConf:edit')")
+    @Log(title = "閲囬泦鍙傛暟閰嶇疆", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody DaCollectionParamConf daCollectionParamConf)
+    {
+        return toAjax(daCollectionParamConfService.updateDaCollectionParamConf(daCollectionParamConf));
+    }
+
+    /**
+     * 鍒犻櫎閲囬泦鍙傛暟閰嶇疆
+     */
+    @PreAuthorize("@ss.hasPermi('da:collectionParamConf:remove')")
+    @Log(title = "閲囬泦鍙傛暟閰嶇疆", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(daCollectionParamConfService.deleteDaCollectionParamConfByIds(ids));
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/da/collectionParamConf/domain/DaCollectionParamConf.java b/jcdm-main/src/main/java/com/jcdm/main/da/collectionParamConf/domain/DaCollectionParamConf.java
new file mode 100644
index 0000000..5e85836
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/da/collectionParamConf/domain/DaCollectionParamConf.java
@@ -0,0 +1,343 @@
+package com.jcdm.main.da.collectionParamConf.domain;
+
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.core.domain.BaseEntity;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 閲囬泦鍙傛暟閰嶇疆瀵硅薄 da_collection_param_conf
+ * 
+ * @author ruimin
+ * @date 2023-12-25
+ */
+public class DaCollectionParamConf extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 涓婚敭id */
+    private Long id;
+
+    /** 宸ュ簭缂栧彿 */
+    @Excel(name = "宸ュ簭缂栧彿")
+    private String processesCode;
+
+    /** 鍙傛暟闆嗙紪鐮� */
+    @Excel(name = "鍙傛暟闆嗙紪鐮�")
+    private String parameterSetCode;
+
+    /** 鍙傛暟闆嗗悕绉� */
+    @Excel(name = "鍙傛暟闆嗗悕绉�")
+    private String parameterSetName;
+
+    /** 閲囬泦鍙傛暟ID */
+    @Excel(name = "閲囬泦鍙傛暟ID")
+    private String collectParameterId;
+
+    /** 閲囬泦鍙傛暟鍚嶇О */
+    @Excel(name = "閲囬泦鍙傛暟鍚嶇О")
+    private String collectParameterName;
+
+    /** 鏄惁浣滀负瀵规瘮鍙傛暟 */
+    @Excel(name = "鏄惁浣滀负瀵规瘮鍙傛暟")
+    private String contrastParameterFlag;
+
+    /** 閲囬泦鍙傛暟绫诲瀷 */
+    @Excel(name = "閲囬泦鍙傛暟绫诲瀷")
+    private String collectParameterType;
+
+    /** 閲囬泦鍙傛暟鍗曚綅 */
+    @Excel(name = "閲囬泦鍙傛暟鍗曚綅")
+    private String collectParameterUnit;
+
+    /** 鏁版嵁鎻忚堪 */
+    @Excel(name = "鏁版嵁鎻忚堪")
+    private String Descriptives;
+
+    /** 涓婇檺鍊� */
+    @Excel(name = "涓婇檺鍊�")
+    private String paramUpper;
+
+    /** 涓嬮檺鍊� */
+    @Excel(name = "涓嬮檺鍊�")
+    private String paramLower;
+
+    /** 涓績鍊� */
+    @Excel(name = "涓績鍊�")
+    private String paramCentral;
+
+    /** 浜у搧缂栫爜 */
+    @Excel(name = "浜у搧缂栫爜")
+    private String productCode;
+
+    /** 閲囬泦鍦板潃 */
+    @Excel(name = "閲囬泦鍦板潃")
+    private String gatherAddress;
+
+    /** 閲囬泦椤哄簭 */
+    @Excel(name = "閲囬泦椤哄簭")
+    private String gatherSequence;
+
+    /** 澶囨敞 */
+    @Excel(name = "澶囨敞")
+    private String remarks;
+
+    /** 鍒涘缓鐢ㄦ埛 */
+    @Excel(name = "鍒涘缓鐢ㄦ埛")
+    private String createUser;
+
+    /** 鏇存敼鐢ㄦ埛 */
+    @Excel(name = "鏇存敼鐢ㄦ埛")
+    private String updateUser;
+
+    /** 棰勭暀瀛楁1 */
+    private String spareField1;
+
+    /** 棰勭暀瀛楁2 */
+    private String spareField2;
+
+    /** 棰勭暀瀛楁3 */
+    private String spareField3;
+
+    /** 棰勭暀瀛楁4 */
+    private String spareField4;
+
+    public void setId(Long id) 
+    {
+        this.id = id;
+    }
+
+    public Long getId() 
+    {
+        return id;
+    }
+    public void setProcessesCode(String processesCode) 
+    {
+        this.processesCode = processesCode;
+    }
+
+    public String getProcessesCode() 
+    {
+        return processesCode;
+    }
+    public void setParameterSetCode(String parameterSetCode) 
+    {
+        this.parameterSetCode = parameterSetCode;
+    }
+
+    public String getParameterSetCode() 
+    {
+        return parameterSetCode;
+    }
+    public void setParameterSetName(String parameterSetName) 
+    {
+        this.parameterSetName = parameterSetName;
+    }
+
+    public String getParameterSetName() 
+    {
+        return parameterSetName;
+    }
+    public void setCollectParameterId(String collectParameterId) 
+    {
+        this.collectParameterId = collectParameterId;
+    }
+
+    public String getCollectParameterId() 
+    {
+        return collectParameterId;
+    }
+    public void setCollectParameterName(String collectParameterName) 
+    {
+        this.collectParameterName = collectParameterName;
+    }
+
+    public String getCollectParameterName() 
+    {
+        return collectParameterName;
+    }
+    public void setContrastParameterFlag(String contrastParameterFlag) 
+    {
+        this.contrastParameterFlag = contrastParameterFlag;
+    }
+
+    public String getContrastParameterFlag() 
+    {
+        return contrastParameterFlag;
+    }
+    public void setCollectParameterType(String collectParameterType) 
+    {
+        this.collectParameterType = collectParameterType;
+    }
+
+    public String getCollectParameterType() 
+    {
+        return collectParameterType;
+    }
+    public void setCollectParameterUnit(String collectParameterUnit) 
+    {
+        this.collectParameterUnit = collectParameterUnit;
+    }
+
+    public String getCollectParameterUnit() 
+    {
+        return collectParameterUnit;
+    }
+    public void setDescriptives(String Descriptives) 
+    {
+        this.Descriptives = Descriptives;
+    }
+
+    public String getDescriptives() 
+    {
+        return Descriptives;
+    }
+    public void setParamUpper(String paramUpper) 
+    {
+        this.paramUpper = paramUpper;
+    }
+
+    public String getParamUpper() 
+    {
+        return paramUpper;
+    }
+    public void setParamLower(String paramLower) 
+    {
+        this.paramLower = paramLower;
+    }
+
+    public String getParamLower() 
+    {
+        return paramLower;
+    }
+    public void setParamCentral(String paramCentral) 
+    {
+        this.paramCentral = paramCentral;
+    }
+
+    public String getParamCentral() 
+    {
+        return paramCentral;
+    }
+    public void setProductCode(String productCode) 
+    {
+        this.productCode = productCode;
+    }
+
+    public String getProductCode() 
+    {
+        return productCode;
+    }
+    public void setGatherAddress(String gatherAddress) 
+    {
+        this.gatherAddress = gatherAddress;
+    }
+
+    public String getGatherAddress() 
+    {
+        return gatherAddress;
+    }
+    public void setGatherSequence(String gatherSequence) 
+    {
+        this.gatherSequence = gatherSequence;
+    }
+
+    public String getGatherSequence() 
+    {
+        return gatherSequence;
+    }
+    public void setRemarks(String remarks) 
+    {
+        this.remarks = remarks;
+    }
+
+    public String getRemarks() 
+    {
+        return remarks;
+    }
+    public void setCreateUser(String createUser) 
+    {
+        this.createUser = createUser;
+    }
+
+    public String getCreateUser() 
+    {
+        return createUser;
+    }
+    public void setUpdateUser(String updateUser) 
+    {
+        this.updateUser = updateUser;
+    }
+
+    public String getUpdateUser() 
+    {
+        return updateUser;
+    }
+    public void setSpareField1(String spareField1) 
+    {
+        this.spareField1 = spareField1;
+    }
+
+    public String getSpareField1() 
+    {
+        return spareField1;
+    }
+    public void setSpareField2(String spareField2) 
+    {
+        this.spareField2 = spareField2;
+    }
+
+    public String getSpareField2() 
+    {
+        return spareField2;
+    }
+    public void setSpareField3(String spareField3) 
+    {
+        this.spareField3 = spareField3;
+    }
+
+    public String getSpareField3() 
+    {
+        return spareField3;
+    }
+    public void setSpareField4(String spareField4) 
+    {
+        this.spareField4 = spareField4;
+    }
+
+    public String getSpareField4() 
+    {
+        return spareField4;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("processesCode", getProcessesCode())
+            .append("parameterSetCode", getParameterSetCode())
+            .append("parameterSetName", getParameterSetName())
+            .append("collectParameterId", getCollectParameterId())
+            .append("collectParameterName", getCollectParameterName())
+            .append("contrastParameterFlag", getContrastParameterFlag())
+            .append("collectParameterType", getCollectParameterType())
+            .append("collectParameterUnit", getCollectParameterUnit())
+            .append("Descriptives", getDescriptives())
+            .append("paramUpper", getParamUpper())
+            .append("paramLower", getParamLower())
+            .append("paramCentral", getParamCentral())
+            .append("productCode", getProductCode())
+            .append("gatherAddress", getGatherAddress())
+            .append("gatherSequence", getGatherSequence())
+            .append("remarks", getRemarks())
+            .append("createUser", getCreateUser())
+            .append("createTime", getCreateTime())
+            .append("updateUser", getUpdateUser())
+            .append("updateTime", getUpdateTime())
+            .append("spareField1", getSpareField1())
+            .append("spareField2", getSpareField2())
+            .append("spareField3", getSpareField3())
+            .append("spareField4", getSpareField4())
+            .toString();
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/da/collectionParamConf/mapper/DaCollectionParamConfMapper.java b/jcdm-main/src/main/java/com/jcdm/main/da/collectionParamConf/mapper/DaCollectionParamConfMapper.java
new file mode 100644
index 0000000..eec648d
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/da/collectionParamConf/mapper/DaCollectionParamConfMapper.java
@@ -0,0 +1,62 @@
+package com.jcdm.main.da.collectionParamConf.mapper;
+
+import com.jcdm.main.da.collectionParamConf.domain.DaCollectionParamConf;
+
+import java.util.List;
+
+/**
+ * 閲囬泦鍙傛暟閰嶇疆Mapper鎺ュ彛
+ * 
+ * @author ruimin
+ * @date 2023-12-25
+ */
+public interface DaCollectionParamConfMapper 
+{
+    /**
+     * 鏌ヨ閲囬泦鍙傛暟閰嶇疆
+     * 
+     * @param id 閲囬泦鍙傛暟閰嶇疆涓婚敭
+     * @return 閲囬泦鍙傛暟閰嶇疆
+     */
+    public DaCollectionParamConf selectDaCollectionParamConfById(Long id);
+
+    /**
+     * 鏌ヨ閲囬泦鍙傛暟閰嶇疆鍒楄〃
+     * 
+     * @param daCollectionParamConf 閲囬泦鍙傛暟閰嶇疆
+     * @return 閲囬泦鍙傛暟閰嶇疆闆嗗悎
+     */
+    public List<DaCollectionParamConf> selectDaCollectionParamConfList(DaCollectionParamConf daCollectionParamConf);
+
+    /**
+     * 鏂板閲囬泦鍙傛暟閰嶇疆
+     * 
+     * @param daCollectionParamConf 閲囬泦鍙傛暟閰嶇疆
+     * @return 缁撴灉
+     */
+    public int insertDaCollectionParamConf(DaCollectionParamConf daCollectionParamConf);
+
+    /**
+     * 淇敼閲囬泦鍙傛暟閰嶇疆
+     * 
+     * @param daCollectionParamConf 閲囬泦鍙傛暟閰嶇疆
+     * @return 缁撴灉
+     */
+    public int updateDaCollectionParamConf(DaCollectionParamConf daCollectionParamConf);
+
+    /**
+     * 鍒犻櫎閲囬泦鍙傛暟閰嶇疆
+     * 
+     * @param id 閲囬泦鍙傛暟閰嶇疆涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteDaCollectionParamConfById(Long id);
+
+    /**
+     * 鎵归噺鍒犻櫎閲囬泦鍙傛暟閰嶇疆
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteDaCollectionParamConfByIds(Long[] ids);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/da/collectionParamConf/service/IDaCollectionParamConfService.java b/jcdm-main/src/main/java/com/jcdm/main/da/collectionParamConf/service/IDaCollectionParamConfService.java
new file mode 100644
index 0000000..8ea5aad
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/da/collectionParamConf/service/IDaCollectionParamConfService.java
@@ -0,0 +1,62 @@
+package com.jcdm.main.da.collectionParamConf.service;
+
+import com.jcdm.main.da.collectionParamConf.domain.DaCollectionParamConf;
+
+import java.util.List;
+
+/**
+ * 閲囬泦鍙傛暟閰嶇疆Service鎺ュ彛
+ * 
+ * @author ruimin
+ * @date 2023-12-25
+ */
+public interface IDaCollectionParamConfService 
+{
+    /**
+     * 鏌ヨ閲囬泦鍙傛暟閰嶇疆
+     * 
+     * @param id 閲囬泦鍙傛暟閰嶇疆涓婚敭
+     * @return 閲囬泦鍙傛暟閰嶇疆
+     */
+    public DaCollectionParamConf selectDaCollectionParamConfById(Long id);
+
+    /**
+     * 鏌ヨ閲囬泦鍙傛暟閰嶇疆鍒楄〃
+     * 
+     * @param daCollectionParamConf 閲囬泦鍙傛暟閰嶇疆
+     * @return 閲囬泦鍙傛暟閰嶇疆闆嗗悎
+     */
+    public List<DaCollectionParamConf> selectDaCollectionParamConfList(DaCollectionParamConf daCollectionParamConf);
+
+    /**
+     * 鏂板閲囬泦鍙傛暟閰嶇疆
+     * 
+     * @param daCollectionParamConf 閲囬泦鍙傛暟閰嶇疆
+     * @return 缁撴灉
+     */
+    public int insertDaCollectionParamConf(DaCollectionParamConf daCollectionParamConf);
+
+    /**
+     * 淇敼閲囬泦鍙傛暟閰嶇疆
+     * 
+     * @param daCollectionParamConf 閲囬泦鍙傛暟閰嶇疆
+     * @return 缁撴灉
+     */
+    public int updateDaCollectionParamConf(DaCollectionParamConf daCollectionParamConf);
+
+    /**
+     * 鎵归噺鍒犻櫎閲囬泦鍙傛暟閰嶇疆
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑閲囬泦鍙傛暟閰嶇疆涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteDaCollectionParamConfByIds(Long[] ids);
+
+    /**
+     * 鍒犻櫎閲囬泦鍙傛暟閰嶇疆淇℃伅
+     * 
+     * @param id 閲囬泦鍙傛暟閰嶇疆涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteDaCollectionParamConfById(Long id);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/da/collectionParamConf/service/impl/DaCollectionParamConfServiceImpl.java b/jcdm-main/src/main/java/com/jcdm/main/da/collectionParamConf/service/impl/DaCollectionParamConfServiceImpl.java
new file mode 100644
index 0000000..fc64873
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/da/collectionParamConf/service/impl/DaCollectionParamConfServiceImpl.java
@@ -0,0 +1,97 @@
+package com.jcdm.main.da.collectionParamConf.service.impl;
+
+import com.jcdm.common.utils.DateUtils;
+import com.jcdm.main.da.collectionParamConf.domain.DaCollectionParamConf;
+import com.jcdm.main.da.collectionParamConf.mapper.DaCollectionParamConfMapper;
+import com.jcdm.main.da.collectionParamConf.service.IDaCollectionParamConfService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 閲囬泦鍙傛暟閰嶇疆Service涓氬姟灞傚鐞�
+ * 
+ * @author ruimin
+ * @date 2023-12-25
+ */
+@Service
+public class DaCollectionParamConfServiceImpl implements IDaCollectionParamConfService 
+{
+    @Autowired
+    private DaCollectionParamConfMapper daCollectionParamConfMapper;
+
+    /**
+     * 鏌ヨ閲囬泦鍙傛暟閰嶇疆
+     * 
+     * @param id 閲囬泦鍙傛暟閰嶇疆涓婚敭
+     * @return 閲囬泦鍙傛暟閰嶇疆
+     */
+    @Override
+    public DaCollectionParamConf selectDaCollectionParamConfById(Long id)
+    {
+        return daCollectionParamConfMapper.selectDaCollectionParamConfById(id);
+    }
+
+    /**
+     * 鏌ヨ閲囬泦鍙傛暟閰嶇疆鍒楄〃
+     * 
+     * @param daCollectionParamConf 閲囬泦鍙傛暟閰嶇疆
+     * @return 閲囬泦鍙傛暟閰嶇疆
+     */
+    @Override
+    public List<DaCollectionParamConf> selectDaCollectionParamConfList(DaCollectionParamConf daCollectionParamConf)
+    {
+        return daCollectionParamConfMapper.selectDaCollectionParamConfList(daCollectionParamConf);
+    }
+
+    /**
+     * 鏂板閲囬泦鍙傛暟閰嶇疆
+     * 
+     * @param daCollectionParamConf 閲囬泦鍙傛暟閰嶇疆
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertDaCollectionParamConf(DaCollectionParamConf daCollectionParamConf)
+    {
+        daCollectionParamConf.setCreateTime(DateUtils.getNowDate());
+        return daCollectionParamConfMapper.insertDaCollectionParamConf(daCollectionParamConf);
+    }
+
+    /**
+     * 淇敼閲囬泦鍙傛暟閰嶇疆
+     * 
+     * @param daCollectionParamConf 閲囬泦鍙傛暟閰嶇疆
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateDaCollectionParamConf(DaCollectionParamConf daCollectionParamConf)
+    {
+        daCollectionParamConf.setUpdateTime(DateUtils.getNowDate());
+        return daCollectionParamConfMapper.updateDaCollectionParamConf(daCollectionParamConf);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎閲囬泦鍙傛暟閰嶇疆
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑閲囬泦鍙傛暟閰嶇疆涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteDaCollectionParamConfByIds(Long[] ids)
+    {
+        return daCollectionParamConfMapper.deleteDaCollectionParamConfByIds(ids);
+    }
+
+    /**
+     * 鍒犻櫎閲囬泦鍙傛暟閰嶇疆淇℃伅
+     * 
+     * @param id 閲囬泦鍙傛暟閰嶇疆涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteDaCollectionParamConfById(Long id)
+    {
+        return daCollectionParamConfMapper.deleteDaCollectionParamConfById(id);
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/cert/KeyStoreLoader.java b/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/cert/KeyStoreLoader.java
new file mode 100644
index 0000000..9b6a4e0
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/cert/KeyStoreLoader.java
@@ -0,0 +1,127 @@
+package com.jcdm.main.da.opcuaconfig.cert;
+
+import org.eclipse.milo.opcua.sdk.server.util.HostnameUtil;
+import org.eclipse.milo.opcua.stack.core.util.SelfSignedCertificateBuilder;
+import org.eclipse.milo.opcua.stack.core.util.SelfSignedCertificateGenerator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.security.*;
+import java.security.cert.X509Certificate;
+import java.util.regex.Pattern;
+
+/**
+ * @ClassName: KeyStoreLoader
+ * @Description: KeyStoreLoader
+ * @author yyt
+ * @date 2023骞�10鏈�13鏃�
+ */
+@Component
+public class KeyStoreLoader {
+
+	private static final Pattern IP_ADDR_PATTERN = Pattern
+			.compile("^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$");
+
+	// 璇佷功鍒悕
+	private static final String CLIENT_ALIAS = "jlclient-ai";
+	// 鑾峰彇绉侀挜鐨勫瘑鐮�
+	private static final char[] PASSWORD = "yyt@8888888888".toCharArray();
+
+	private final Logger logger = LoggerFactory.getLogger(getClass());
+
+	// 璇佷功瀵硅薄
+	private X509Certificate clientCertificate;
+	// 瀵嗛挜瀵瑰璞�
+	private KeyPair clientKeyPair;
+
+	/**
+	 * @MethodName: load
+	 * @Description: load
+	 * @param baseDir
+	 * @return
+	 * @throws Exception
+	 * @CreateTime 2023骞�10鏈�13鏃�
+	 */
+	public KeyStoreLoader load(Path baseDir) throws Exception {
+		// 鍒涘缓涓�涓娇鐢╜PKCS12`鍔犲瘑鏍囧噯鐨凨eyStore銆侹eyStore鍦ㄥ悗闈㈠皢浣滀负璇诲彇鍜岀敓鎴愯瘉涔︾殑瀵硅薄銆�
+		KeyStore keyStore = KeyStore.getInstance("PKCS12");
+
+		// PKCS12鐨勫姞瀵嗘爣鍑嗙殑鏂囦欢鍚庣紑鏄�.pfx锛屽叾涓寘鍚簡鍏挜鍜岀閽ャ��
+		// 鑰屽叾浠栧.der绛夌殑鏍煎紡鍙寘鍚叕閽ワ紝绉侀挜鍦ㄥ彟澶栫殑鏂囦欢涓��
+		Path serverKeyStore = baseDir.resolve("OPCUA-client.pfx");
+
+		logger.info("Loading KeyStore at {}", serverKeyStore);
+
+		// 濡傛灉鏂囦欢涓嶅瓨鍦ㄥ垯鍒涘缓.pfx璇佷功鏂囦欢銆�
+		if (!Files.exists(serverKeyStore)) {
+			keyStore.load(null, PASSWORD);
+
+			// 鐢�2048浣嶇殑RAS绠楁硶銆俙SelfSignedCertificateGenerator`涓篗ilo搴撶殑瀵硅薄銆�
+			KeyPair keyPair = SelfSignedCertificateGenerator.generateRsaKeyPair(2048);
+
+			// `SelfSignedCertificateBuilder`涔熸槸Milo搴撶殑瀵硅薄锛岀敤鏉ョ敓鎴愯瘉涔︺��
+			// 涓棿鎵�璁剧疆鐨勮瘉涔﹀睘鎬у彲浠ヨ嚜琛屼慨鏀广��
+			SelfSignedCertificateBuilder builder = new SelfSignedCertificateBuilder(keyPair)
+					.setCommonName("UaClient@Jellyleo")
+					.setOrganization("JL")
+					.setOrganizationalUnit("per")
+					.setLocalityName("jl")
+					.setStateName("JiangSu")
+					.setCountryCode("CN")
+					.setApplicationUri("urn:Yyt_PC:UnifiedAutomation:UaExpert")
+					.addDnsName("Yyt_PC")
+					.addIpAddress("127.0.0.1");
+
+			// Get as many hostnames and IP addresses as we can listed in the certificate.
+			for (String hostname : HostnameUtil.getHostnames("0.0.0.0")) {
+				if (IP_ADDR_PATTERN.matcher(hostname).matches()) {
+					builder.addIpAddress(hostname);
+				} else {
+					builder.addDnsName(hostname);
+				}
+			}
+			// 鍒涘缓璇佷功
+			X509Certificate certificate = builder.build();
+
+			// 璁剧疆瀵瑰簲绉侀挜鐨勫埆鍚嶏紝瀵嗙爜锛岃瘉涔﹂摼
+			keyStore.setKeyEntry(CLIENT_ALIAS, keyPair.getPrivate(), PASSWORD, new X509Certificate[] { certificate });
+			try (OutputStream out = Files.newOutputStream(serverKeyStore)) {
+				// 淇濆瓨璇佷功鍒拌緭鍑烘祦
+				keyStore.store(out, PASSWORD);
+			}
+		} else {
+			try (InputStream in = Files.newInputStream(serverKeyStore)) {
+				// 濡傛灉鏂囦欢瀛樺湪鍒欒鍙�
+				keyStore.load(in, PASSWORD);
+			}
+		}
+
+		// 鐢ㄥ瘑鐮佽幏鍙栧搴斿埆鍚嶇殑绉侀挜銆�
+		Key serverPrivateKey = keyStore.getKey(CLIENT_ALIAS, PASSWORD);
+		if (serverPrivateKey instanceof PrivateKey) {
+			// 鑾峰彇瀵瑰簲鍒悕鐨勮瘉涔﹀璞°��
+			clientCertificate = (X509Certificate) keyStore.getCertificate(CLIENT_ALIAS);
+			// 鑾峰彇鍏挜
+			PublicKey serverPublicKey = clientCertificate.getPublicKey();
+			// 鍒涘缓Keypair瀵硅薄銆�
+			clientKeyPair = new KeyPair(serverPublicKey, (PrivateKey) serverPrivateKey);
+		}
+
+		return this;
+	}
+
+	// 杩斿洖璇佷功
+	public X509Certificate getClientCertificate() {
+		return clientCertificate;
+	}
+
+	// 杩斿洖瀵嗛挜瀵�
+	public KeyPair getClientKeyPair() {
+		return clientKeyPair;
+	}
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/cert/MethodName.java b/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/cert/MethodName.java
new file mode 100644
index 0000000..2fe1773
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/cert/MethodName.java
@@ -0,0 +1,169 @@
+package com.jcdm.main.da.opcuaconfig.cert;
+
+import com.jcdm.framework.websocket.WebSocketServer;
+import com.jcdm.framework.websocket.WebSocketUsers;
+import com.jcdm.main.bs.formulaChild.domain.BsFormulaChildInfo;
+import com.jcdm.main.bs.formulaChild.service.IBsFormulaChildInfoService;
+import com.jcdm.main.da.collectionParamConf.domain.DaCollectionParamConf;
+import com.jcdm.main.da.collectionParamConf.service.IDaCollectionParamConfService;
+import com.jcdm.main.da.opcuaconfig.client.ClientHandler;
+import com.jcdm.main.da.opcuaconfig.domain.NodeEntity;
+import com.jcdm.main.da.opcuaconfig.init.BeanUtils;
+import com.jcdm.main.da.paramCollection.domain.DaParamCollection;
+import com.jcdm.main.da.paramCollection.service.IDaParamCollectionService;
+import com.jcdm.main.da.passingStationCollection.domain.DaPassingStationCollection;
+import com.jcdm.main.da.passingStationCollection.service.IDaPassingStationCollectionService;
+import lombok.extern.slf4j.Slf4j;
+import org.eclipse.milo.opcua.stack.core.types.builtin.DataValue;
+import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId;
+
+import javax.websocket.Session;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import static com.jcdm.main.da.opcuaconfig.client.ClientHandler.readValues;
+
+@Slf4j
+public class MethodName {
+    Map<String, Session> map = WebSocketUsers.getUsers();
+    private IDaCollectionParamConfService collectionParamConfService = BeanUtils.getBean(IDaCollectionParamConfService.class);
+    private IDaParamCollectionService daParamCollectionService = BeanUtils.getBean(IDaParamCollectionService.class);
+    private IDaPassingStationCollectionService daPassingStationCollectionService = BeanUtils.getBean(IDaPassingStationCollectionService.class);
+    private IBsFormulaChildInfoService bsFormulaChildInfoService = BeanUtils.getBean(IBsFormulaChildInfoService.class);
+    private List<DataValue> s=null;
+    public void Transit(String Node, String value) throws Exception {
+        log.info(Node+":"+value);
+        String[] parts = Node.split("[.]");
+        ClientHandler clientHandler=new ClientHandler();
+        NodeEntity SN_node= NodeEntity.builder().index(2).identifier(parts[0]+"."+parts[1]+".SNCode").value("").type("").build();
+        String SNCode=clientHandler.read(SN_node);
+        log.info("璇诲彇鑺傜偣:{},缁撴灉:{}", SN_node.getIdentifier(),SNCode);
+        switch (value) {
+            case "0":   //鍒濆
+                NodeEntity node= NodeEntity.builder().index(2).identifier(parts[0]+"."+parts[1]+".RecordDataDone").value("0").type("short").build();
+                Boolean out=clientHandler.write(node);
+                log.info("鑺傜偣:{},鍝嶅簲缁撴灉:{}", node.getIdentifier(),out);
+                break;
+            case "1":   //璇锋眰涓嬪彂杩涚珯鐘舵��
+                NodeEntity node1= NodeEntity.builder().index(2).identifier(parts[0]+"."+parts[1]+".RecordDataDone").value("11").type("short").build();
+                Boolean out1=clientHandler.write(node1);
+                DaPassingStationCollection PassingStationCollection=new DaPassingStationCollection();
+                PassingStationCollection.setSfcCode(SNCode);
+                PassingStationCollection.setLocationCode(parts[1]);
+                PassingStationCollection.setInboundTime(new Date());
+                daPassingStationCollectionService.insertDaPassingStationCollection(PassingStationCollection);
+                log.info("鑺傜偣:{},鍝嶅簲缁撴灉:{}", node1.getIdentifier(),out1);
+                WebSocketUsers.sendMessageToUserByText(map.get(parts[1]), "IN");
+                break;
+            case "2":   //璇锋眰璁板綍宸ヤ綅鏁版嵁
+                List<DaCollectionParamConf> b;
+                DaCollectionParamConf daCollectionParamConf=new DaCollectionParamConf();
+                daCollectionParamConf.setGatherAddress(parts[0]+"."+parts[1]);
+                b=collectionParamConfService.selectDaCollectionParamConfList(daCollectionParamConf);
+
+                List<NodeId> nodeId = b.stream().map(info -> {
+                    NodeId nodeid = new NodeId(2,info.getGatherAddress());
+                    return nodeid;
+                }).collect(Collectors.toList());
+                List<DataValue> s=readValues(nodeId);
+                //淇濆瓨PLC閲囬泦鏁版嵁
+                for(int i=0;i<nodeId.size();i++)
+                {
+                    DaParamCollection Config=new DaParamCollection();
+                    Config.setParamCode(nodeId.get(i).getIdentifier().toString().split("[.]")[2]);
+                    Config.setLocationCode(nodeId.get(i).getIdentifier().toString().split("[.]")[1]);
+                    Config.setParamValue(s.get(i).getValue().getValue().toString());
+                    Config.setSfcCode(SNCode);
+                    Config.setParamName(b.get(i).getGatherAddress());
+                    daParamCollectionService.insertDaParamCollection(Config);
+                }
+                //鏇存柊鍑虹珯鏃堕棿锛岃绠楄妭鎷嶃��
+                DaPassingStationCollection PSC=new DaPassingStationCollection();
+                PSC.setSfcCode(SNCode);
+                List<DaPassingStationCollection> LPSC=daPassingStationCollectionService.selectDaPassingStationCollectionList(PSC);
+                if(LPSC != null && LPSC.size() > 0){
+                    LPSC.get(0).setOutboundTime(new Date());
+                    LPSC.get(0).setCollectionTime(new Date());
+                    LPSC.get(0).setBeatTime(Long.toString(Math.abs(new Date().getTime() - LPSC.get(0).getInboundTime().getTime())));
+                    daPassingStationCollectionService.updateDaPassingStationCollection(LPSC.get(0));
+                }
+                //鏇存柊PLC鑺傜偣鐘舵��
+                NodeEntity node2= NodeEntity.builder().index(2).identifier(parts[0]+"."+parts[1]+".RecordDataDone").value("21").type("short").build();
+                Boolean out2=clientHandler.write(node2);
+                WebSocketUsers.sendMessageToUserByText(map.get(parts[1]), "OUT");
+                log.info("鑺傜偣:{},鍝嶅簲缁撴灉:{}", node2.getIdentifier(),out2);
+                break;
+            default:
+                break;
+        }
+    }
+
+    public void tighten(String Node, String value) throws Exception {
+        String[] parts = Node.split("[.]");
+        ClientHandler clientHandler=new ClientHandler();
+        System.out.println("Node:"+Node+"value:"+value);
+        switch (value){
+            case "1":
+                //璇绘壄鐭�
+                NodeEntity SN_node= NodeEntity.builder().index(2).identifier(parts[0]+"."+parts[1]+".RecordSN").value("").type("").build();
+                String SNCode=clientHandler.read(SN_node);
+
+                //璇昏搴�
+                NodeEntity SNDone= NodeEntity.builder().index(2).identifier(parts[0]+"."+parts[1]+".RecordSNDone").value("").type("").build();
+                String RecordSNDone = clientHandler.read(SNDone);
+
+                //璇荤粨鏋�
+                NodeEntity SNDone1= NodeEntity.builder().index(2).identifier(parts[0]+"."+parts[1]+".WorkID").value("").type("").build();
+                String WorkID = clientHandler.read(SNDone1);
+
+                //淇濆瓨鍙傛暟閲囬泦琛�
+                DaParamCollection paramCollection = new DaParamCollection();
+                paramCollection.setLocationCode(parts[1]);
+                paramCollection.setParamCode("RecordSN");
+                paramCollection.setParamValue(SNCode);
+                paramCollection.setParamName(parts[0]+"."+parts[1]+".RecordSN");
+                daParamCollectionService.insertDaParamCollection(paramCollection);
+
+
+                DaParamCollection paramCollection1 = new DaParamCollection();
+                paramCollection1.setLocationCode(parts[1]);
+                paramCollection1.setParamCode("RecordSNDone");
+                paramCollection1.setParamValue(RecordSNDone);
+                paramCollection1.setParamName(parts[0]+"."+parts[1]+".RecordSNDone");
+                daParamCollectionService.insertDaParamCollection(paramCollection1);
+
+
+
+                DaParamCollection paramCollection2 = new DaParamCollection();
+                paramCollection2.setLocationCode(parts[1]);
+                paramCollection2.setParamCode("WorkID");
+                paramCollection2.setParamValue(WorkID);
+                paramCollection2.setParamName(parts[0]+"."+parts[1]+".WorkID");
+                daParamCollectionService.insertDaParamCollection(paramCollection2);
+
+                //淇濆瓨鐘舵�佹洿鏂板墠绔〃鍗�
+                BsFormulaChildInfo test = bsFormulaChildInfoService.selectBsFormulaChildInfoByTypeTopOne("1", "test", parts[1]);
+                test.setResults(WorkID);
+                bsFormulaChildInfoService.updateBsFormulaChildInfo(test);
+                WebSocketUsers.sendMessageToUserByText(map.get(parts[1]), "TIGHTEN");
+
+
+
+                System.out.println("SNCode:"+SNCode);
+                System.out.println("Node:"+Node+"value:"+value);
+                NodeEntity node= NodeEntity.builder().index(2).identifier(parts[0]+"."+parts[1]+".StationStatus").value("0").type("short").build();
+                Boolean out=clientHandler.write(node);
+                NodeEntity RecordSN= NodeEntity.builder().index(2).identifier(parts[0]+"."+parts[1]+".RecordSN").value("0").type("short").build();
+                Boolean out1=clientHandler.write(RecordSN);
+                NodeEntity riteRecordSNDone= NodeEntity.builder().index(2).identifier(parts[0]+"."+parts[1]+".RecordSNDone").value("0").type("short").build();
+                Boolean out2=clientHandler.write(riteRecordSNDone);
+                log.info("鑺傜偣:{},鍝嶅簲缁撴灉:{}", node.getIdentifier(),out);
+            default:
+                break;
+        }
+    }
+
+
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/client/ClientHandler.java b/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/client/ClientHandler.java
new file mode 100644
index 0000000..a6e01b5
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/client/ClientHandler.java
@@ -0,0 +1,295 @@
+package com.jcdm.main.da.opcuaconfig.client;
+
+import com.google.common.collect.ImmutableList;
+import com.jcdm.main.da.opcuaconfig.domain.DaOpcuaConfig;
+import com.jcdm.main.da.opcuaconfig.domain.NodeEntity;
+import com.jcdm.main.da.opcuaconfig.service.IDaOpcuaConfigService;
+import lombok.extern.slf4j.Slf4j;
+import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
+import org.eclipse.milo.opcua.sdk.client.api.nodes.VariableNode;
+import org.eclipse.milo.opcua.sdk.client.api.subscriptions.UaSubscription;
+import org.eclipse.milo.opcua.stack.core.AttributeId;
+import org.eclipse.milo.opcua.stack.core.BuiltinDataType;
+import org.eclipse.milo.opcua.stack.core.types.builtin.DataValue;
+import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId;
+import org.eclipse.milo.opcua.stack.core.types.builtin.StatusCode;
+import org.eclipse.milo.opcua.stack.core.types.builtin.Variant;
+import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned;
+import org.eclipse.milo.opcua.stack.core.types.enumerated.MonitoringMode;
+import org.eclipse.milo.opcua.stack.core.types.enumerated.TimestampsToReturn;
+import org.eclipse.milo.opcua.stack.core.types.structured.MonitoredItemCreateRequest;
+import org.eclipse.milo.opcua.stack.core.types.structured.MonitoringParameters;
+import org.eclipse.milo.opcua.stack.core.types.structured.ReadValueId;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+
+/**
+ * @ClassName: ClientHandler
+ * @Description: 瀹㈡埛绔鐞�
+ * @author Jellyleo
+ * @date 2019骞�12鏈�12鏃�
+ */
+@Slf4j
+@Service
+public class ClientHandler {
+
+	// 瀹㈡埛绔疄渚�
+	public static OpcUaClient client = null;
+
+	public List<DaOpcuaConfig> b = null;
+
+	@Autowired
+	private ClientRunner clientRunner;
+
+	@Autowired
+	private IDaOpcuaConfigService daOpcuaConfigService;
+
+
+	/**
+	 * 
+	 * @MethodName: connect
+	 * @Description: connect
+	 * @throws Exception
+	 * @CreateTime 2019骞�12鏈�18鏃� 涓婂崍10:41:09
+	 */
+	public String connect() throws Exception {
+
+		if (client != null) {
+			return "瀹㈡埛绔凡鍒涘缓";
+		}
+
+		client = clientRunner.run();
+
+		if (client == null) {
+			return "瀹㈡埛绔厤缃疄渚嬪寲澶辫触";
+		}
+
+		// 鍒涘缓杩炴帴
+		client.connect().get();
+		return "鍒涘缓杩炴帴鎴愬姛";
+	}
+
+	/**
+	 * @MethodName: disconnect
+	 * @Description: 鏂紑杩炴帴
+	 * @return
+	 * @throws Exception
+	 * @CreateTime 2019骞�12鏈�18鏃� 涓婂崍10:45:21
+	 */
+	public String disconnect() throws Exception {
+
+		if (client == null) {
+			return "杩炴帴宸叉柇寮�";
+		}
+
+		// 鏂紑杩炴帴
+		clientRunner.getFuture().complete(client);
+		client = null;
+		return "鏂紑杩炴帴鎴愬姛";
+	}
+
+	/**
+	 * @MethodName: subscribe
+	 * @Description: 璁㈤槄鑺傜偣鍙橀噺
+	 * @throws Exception
+	 * @CreateTime 2019骞�12鏈�18鏃� 涓婂崍10:38:11
+	 */
+	public String subscribe(List<NodeEntity> nodes) throws Exception {
+
+		if (client == null) {
+			return "鎵句笉鍒板鎴风锛屾搷浣滃け璐�";
+		}
+
+		// 鏌ヨ璁㈤槄瀵硅薄锛屾病鏈夊垯鍒涘缓
+		UaSubscription subscription = null;
+		ImmutableList<UaSubscription> subscriptionList = client.getSubscriptionManager().getSubscriptions();
+		if (CollectionUtils.isEmpty(subscriptionList)) {
+			subscription = client.getSubscriptionManager().createSubscription(1000.0).get();
+		} else {
+			subscription = subscriptionList.get(0);
+		}
+
+		// 鐩戞帶椤硅姹傚垪琛�
+		List<MonitoredItemCreateRequest> requests = new ArrayList<>();
+
+		if (!CollectionUtils.isEmpty(nodes)) {
+			for (NodeEntity node : nodes) {
+				// 鍒涘缓鐩戞帶鐨勫弬鏁�
+				MonitoringParameters parameters = new MonitoringParameters(subscription.nextClientHandle(), 1000.0, // sampling
+						// interval
+						null, // filter, null means use default
+						Unsigned.uint(10), // queue size
+						true // discard oldest
+				);
+				// 鍒涘缓璁㈤槄鐨勫彉閲忥紝 鍒涘缓鐩戞帶椤硅 姹�
+				MonitoredItemCreateRequest request = new MonitoredItemCreateRequest(
+						new ReadValueId(new NodeId(node.getIndex(), node.getIdentifier()), AttributeId.Value.uid(),
+								null, null),
+						MonitoringMode.Reporting, parameters);
+				requests.add(request);
+			}
+		}
+
+		// 鍒涘缓鐩戞帶椤癸紝骞朵笖娉ㄥ唽鍙橀噺鍊兼敼鍙樻椂鍊欑殑鍥炶皟鍑芥暟
+		subscription.createMonitoredItems(TimestampsToReturn.Both, requests, (item, id) -> {
+			item.setValueConsumer((i, v) -> {
+				handle(i.getReadValueId().getNodeId(), v.getValue());
+			});
+		}).get();
+
+		return "璁㈤槄鎴愬姛";
+	}
+
+	/**
+	 * * @MethodName: write
+	 * @Description: 鍥炶皟鍑芥暟
+	 * @CreateTime 2023骞�10鏈�13鏃�
+	 */
+	public void handle(NodeId id, Variant value){
+		if (b == null || 0 > b.size()) {
+			DaOpcuaConfig opcuaConfParam=new DaOpcuaConfig();
+		    opcuaConfParam.setSubscribe("Y");
+		    b=daOpcuaConfigService.selectDaOpcuaConfigList(opcuaConfParam);
+		}
+		//浣跨敤Stream API鍦↙ist<T>涓煡鎵惧厓绱�
+		DaOpcuaConfig daOpcuaConfig = b.stream()
+				.filter(customer ->id.getIdentifier().toString().equals(customer.getNode()))
+				.findAny()
+				.orElse(null);
+		try {
+			Class<?> clazz = Class.forName("com.jcdm.main.da.opcuaconfig.cert.MethodName");
+			Method method = clazz.getMethod(daOpcuaConfig.getrFunction(), new Class[] { String.class, String.class });
+			method.invoke(clazz.newInstance(),new Object[] {
+					new String(id.getIdentifier().toString()), new String(value.getValue().toString()) });
+		} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InstantiationException |
+				 InvocationTargetException e) {
+			e.printStackTrace();
+		}
+	}
+
+
+	/**
+	 * @MethodName: write
+	 * @Description: 鍙樿妭鐐归噺鍐欏叆
+	 * @param node
+	 * @throws Exception
+	 * @CreateTime 2019骞�12鏈�18鏃� 涓婂崍9:51:40
+	 */
+	public static Boolean write(NodeEntity node) throws Exception {
+
+		if (client == null) {
+			log.info("鎵句笉鍒板鎴风锛屾搷浣滃け璐�");
+			return false;
+		}
+
+		NodeId nodeId = new NodeId(node.getIndex(), node.getIdentifier());
+		Variant value = null;
+		switch (node.getType()) {
+		case "int":
+			value = new Variant(Integer.parseInt(node.getValue().toString()));
+			break;
+		case "boolean":
+			value = new Variant(Boolean.parseBoolean(node.getValue().toString()));
+			break;
+		case "short":
+			value = new Variant(Short.parseShort(node.getValue().toString()));
+			break;
+		case "long":
+			value = new Variant(Long.parseLong(node.getValue().toString()));
+			break;
+		case "string":
+			value = new Variant(node.getValue().toString());
+			break;
+		case "char":
+			value = new Variant(node.getValue().toString().charAt(0));
+			break;
+		}
+		DataValue dataValue = new DataValue(value, null, null);
+
+		StatusCode statusCode = client.writeValue(nodeId, dataValue).get();
+
+		return statusCode.isGood();
+	}
+
+	/**
+	 * 鏂规硶鎻忚堪: 璇诲彇澶氫釜鐐逛綅鐨勫��
+	 *
+	 * @param nodeIdList 鐐逛綅闆嗗悎
+	 * @return {@link List<DataValue>}
+	 * @throws
+	 */
+	public static List<DataValue> readValues(List<NodeId> nodeIdList){
+		try {
+			List<DataValue> dataValues=client.readValues(0.0, TimestampsToReturn.Both,nodeIdList).get();
+			return dataValues;
+		} catch (InterruptedException | ExecutionException e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+	/**
+	 * @MethodName: read
+	 * @Description: 璇诲彇
+	 * @param node
+	 * @return
+	 * @throws Exception
+	 * @CreateTime 2019骞�12鏈�19鏃� 涓嬪崍2:40:34
+	 */
+	public String read(NodeEntity node) throws Exception {
+
+		if (client == null) {
+			return "鎵句笉鍒板鎴风锛屾搷浣滃け璐�";
+		}
+
+		NodeId nodeId = new NodeId(node.getIndex(), node.getIdentifier());
+		VariableNode vnode = client.getAddressSpace().createVariableNode(nodeId);
+		DataValue value = vnode.readValue().get();
+		log.info("Value={}", value);
+
+		Variant variant = value.getValue();
+		log.info("Variant={}", variant.getValue());
+
+		log.info("BackingClass={}", BuiltinDataType.getBackingClass(variant.getDataType().get()));
+
+		return variant.getValue().toString();
+	}
+
+
+	/**
+	 * 鏂规硶鎻忚堪:  鍐欏叆澶氫釜鑺傜偣鐨勫��
+	 *
+	 * @param keys  鑺傜偣闆嗗悎
+	 * @param values  鍊奸泦鍚�
+	 * @param client  瀹㈡埛绔�
+	 * @return {@link Object}
+	 * @throws
+	 */
+	public static Object writeValues(Set<String> keys, List<Object> values, OpcUaClient client){
+		List<NodeId> nodeIs=new ArrayList<>(keys.size());
+		keys.forEach(e->{
+			NodeId nodeId = new NodeId(2, e);
+			nodeIs.add(nodeId);
+		});
+		List<DataValue> dataValues=new ArrayList<>(values.size());
+		values.forEach(e->{
+			Variant value=new Variant(Double.parseDouble(e.toString()));
+			DataValue dataValue=new DataValue(value);
+			dataValues.add(dataValue);
+		});
+		try {
+			client.writeValues(nodeIs,dataValues).get();
+		} catch (InterruptedException | ExecutionException e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/client/ClientRunner.java b/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/client/ClientRunner.java
new file mode 100644
index 0000000..513a6dd
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/client/ClientRunner.java
@@ -0,0 +1,146 @@
+package com.jcdm.main.da.opcuaconfig.client;
+
+import com.jcdm.main.da.opcuaconfig.cert.KeyStoreLoader;
+import com.jcdm.main.da.opcuaconfig.init.Properties;
+import lombok.extern.slf4j.Slf4j;
+import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
+import org.eclipse.milo.opcua.sdk.client.api.config.OpcUaClientConfig;
+import org.eclipse.milo.opcua.sdk.client.api.identity.AnonymousProvider;
+import org.eclipse.milo.opcua.stack.client.DiscoveryClient;
+import org.eclipse.milo.opcua.stack.core.Stack;
+import org.eclipse.milo.opcua.stack.core.security.SecurityPolicy;
+import org.eclipse.milo.opcua.stack.core.types.builtin.LocalizedText;
+import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned;
+import org.eclipse.milo.opcua.stack.core.types.structured.EndpointDescription;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.function.Predicate;
+
+/**
+ * @ClassName: ClientRunner
+ * @Description: 瀹㈡埛绔惎鍔ㄧ被
+ * @author yyt
+ * @date 2023骞�10鏈�13鏃�
+ */
+@Slf4j
+@Component
+public class ClientRunner {
+
+	private final CompletableFuture<OpcUaClient> future = new CompletableFuture<>();
+
+	@Autowired
+	private Properties properties;
+
+	@Autowired
+	private KeyStoreLoader keyStoreLoader;
+
+	/**
+	 * @MethodName: run
+	 * @Description: 鍚姩
+	 * @return
+	 * @throws Exception
+	 * @CreateTime 2023骞�10鏈�13鏃�
+	 */
+	public OpcUaClient run() throws Exception {
+
+		OpcUaClient client = createClient();
+
+		future.whenCompleteAsync((c, ex) -> {
+			if (ex != null) {
+				log.error("Error running example: {}", ex.getMessage(), ex);
+			}
+
+			try {
+				c.disconnect().get();
+				Stack.releaseSharedResources();
+			} catch (InterruptedException | ExecutionException e) {
+				log.error("Error disconnecting:", e.getMessage(), e);
+			}
+		});
+
+		return client;
+	}
+
+	/**
+	 * @MethodName: createClient
+	 * @Description: 鍒涘缓瀹㈡埛绔�
+	 * @return
+	 * @throws Exception
+	 * @CreateTime 2023骞�10鏈�13鏃�
+	 */
+	private OpcUaClient createClient() throws Exception {
+
+		Path securityTempDir = Paths.get(properties.getCertPath(), "security");
+		Files.createDirectories(securityTempDir);
+		if (!Files.exists(securityTempDir)) {
+			log.error("unable to create security dir: " + securityTempDir);
+			return null;
+		}
+
+		KeyStoreLoader loader = keyStoreLoader.load(securityTempDir);
+
+		// 鎼滅储OPC鑺傜偣
+		List<EndpointDescription> endpoints = null;
+		try {
+			//鑾峰彇瀹夊叏绛栫暐
+			endpoints = DiscoveryClient.getEndpoints(properties.getEndpointUrl()).get();
+		} catch (Throwable e) {
+			// try the explicit discovery endpoint as well
+			String discoveryUrl = properties.getEndpointUrl();
+
+			if (!discoveryUrl.endsWith("/")) {
+				discoveryUrl += "/";
+			}
+			discoveryUrl += "discovery";
+
+			log.info("Trying explicit discovery URL: {}", discoveryUrl);
+			endpoints = DiscoveryClient.getEndpoints(discoveryUrl).get();
+		}
+
+		EndpointDescription endpoint = endpoints.stream()
+				.filter(e -> e.getSecurityPolicyUri().equals(SecurityPolicy.None.getUri())).filter(endpointFilter())
+				.findFirst().orElseThrow(() -> new Exception("no desired endpoints returned"));
+
+		OpcUaClientConfig config = OpcUaClientConfig.builder()
+				// opc ua鑷畾涔夌殑鍚嶇О
+				.setApplicationName(LocalizedText.english("plc"))
+				// 鍦板潃
+				.setApplicationUri(properties.getEndpointUrl())
+				.setCertificate(loader.getClientCertificate()).setKeyPair(loader.getClientKeyPair())
+				// 瀹夊叏绛栫暐绛夐厤缃�
+				//.setEndpoint(endpoint).setIdentityProvider(new UsernameProvider("OPCUA", "yyt@8888888888"))
+				.setEndpoint(endpoint)
+				// 鍖垮悕楠岃瘉
+				.setIdentityProvider(new AnonymousProvider())
+				//绛夊緟鏃堕棿
+				.setRequestTimeout(Unsigned.uint(5000)).build();
+
+		return OpcUaClient.create(config);
+
+	}
+
+	/**
+	 * @MethodName: endpointFilter
+	 * @Description: endpointFilter
+	 * @return
+	 * @CreateTime 2023骞�10鏈�13鏃�
+	 */
+	private Predicate<EndpointDescription> endpointFilter() {
+		return e -> true;
+	}
+
+	/**
+	 * @return the future
+	 */
+	public CompletableFuture<OpcUaClient> getFuture() {
+		return future;
+	}
+
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/controller/DaOpcuaConfigController.java b/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/controller/DaOpcuaConfigController.java
new file mode 100644
index 0000000..b052a20
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/controller/DaOpcuaConfigController.java
@@ -0,0 +1,98 @@
+package com.jcdm.main.da.opcuaconfig.controller;
+
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.core.page.TableDataInfo;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.common.utils.poi.ExcelUtil;
+import com.jcdm.main.da.opcuaconfig.domain.DaOpcuaConfig;
+import com.jcdm.main.da.opcuaconfig.service.IDaOpcuaConfigService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+
+/**
+ * 浜や簰淇″彿閰嶇疆Controller
+ * 
+ * @author yyt
+ * @date 2024-01-23
+ */
+@RestController
+@RequestMapping("/da/opcuaconfig")
+public class DaOpcuaConfigController extends BaseController
+{
+    @Autowired
+    private IDaOpcuaConfigService daOpcuaConfigService;
+
+    /**
+     * 鏌ヨ浜や簰淇″彿閰嶇疆鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('da:opcuaconfig:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(DaOpcuaConfig daOpcuaConfig)
+    {
+        startPage();
+        List<DaOpcuaConfig> list = daOpcuaConfigService.selectDaOpcuaConfigList(daOpcuaConfig);
+        return getDataTable(list);
+    }
+
+    /**
+     * 瀵煎嚭浜や簰淇″彿閰嶇疆鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('da:opcuaconfig:export')")
+    @Log(title = "浜や簰淇″彿閰嶇疆", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, DaOpcuaConfig daOpcuaConfig)
+    {
+        List<DaOpcuaConfig> list = daOpcuaConfigService.selectDaOpcuaConfigList(daOpcuaConfig);
+        ExcelUtil<DaOpcuaConfig> util = new ExcelUtil<DaOpcuaConfig>(DaOpcuaConfig.class);
+        util.exportExcel(response, list, "浜や簰淇″彿閰嶇疆鏁版嵁");
+    }
+
+    /**
+     * 鑾峰彇浜や簰淇″彿閰嶇疆璇︾粏淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('da:opcuaconfig:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(daOpcuaConfigService.selectDaOpcuaConfigById(id));
+    }
+
+    /**
+     * 鏂板浜や簰淇″彿閰嶇疆
+     */
+    @PreAuthorize("@ss.hasPermi('da:opcuaconfig:add')")
+    @Log(title = "浜や簰淇″彿閰嶇疆", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody DaOpcuaConfig daOpcuaConfig)
+    {
+        return toAjax(daOpcuaConfigService.insertDaOpcuaConfig(daOpcuaConfig));
+    }
+
+    /**
+     * 淇敼浜や簰淇″彿閰嶇疆
+     */
+    @PreAuthorize("@ss.hasPermi('da:opcuaconfig:edit')")
+    @Log(title = "浜や簰淇″彿閰嶇疆", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody DaOpcuaConfig daOpcuaConfig)
+    {
+        return toAjax(daOpcuaConfigService.updateDaOpcuaConfig(daOpcuaConfig));
+    }
+
+    /**
+     * 鍒犻櫎浜や簰淇″彿閰嶇疆
+     */
+    @PreAuthorize("@ss.hasPermi('da:opcuaconfig:remove')")
+    @Log(title = "浜や簰淇″彿閰嶇疆", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(daOpcuaConfigService.deleteDaOpcuaConfigByIds(ids));
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/domain/DaOpcuaConfig.java b/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/domain/DaOpcuaConfig.java
new file mode 100644
index 0000000..f9ea5ac
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/domain/DaOpcuaConfig.java
@@ -0,0 +1,149 @@
+package com.jcdm.main.da.opcuaconfig.domain;
+
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.core.domain.BaseEntity;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 浜や簰淇″彿閰嶇疆瀵硅薄 da_opcua_config
+ * 
+ * @author yyt
+ * @date 2024-01-23
+ */
+public class DaOpcuaConfig extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** ID */
+    private Long id;
+
+    /** 鑺傜偣 */
+    @Excel(name = "鑺傜偣")
+    private String node;
+
+    /** 鏁版嵁绫诲瀷 */
+    @Excel(name = "鏁版嵁绫诲瀷")
+    private String sysTypes;
+
+    /** 鏄惁璁㈤槄 */
+    @Excel(name = "鏄惁璁㈤槄")
+    private String subscribe;
+
+    /** 璁㈤槄绫诲瀷 */
+    @Excel(name = "璁㈤槄绫诲瀷")
+    private String rFunction;
+
+    /** 澶囨敞 */
+    @Excel(name = "澶囨敞")
+    private String remarks;
+
+    /** 宸ュ簭鍚嶇О */
+    @Excel(name = "宸ュ簭鍚嶇О")
+    private String processName;
+
+    /** 宸ュ簭缂栫爜 */
+    @Excel(name = "宸ュ簭缂栫爜")
+    private String process;
+
+    /** 鐘舵�� */
+    @Excel(name = "鐘舵��")
+    private Long state;
+
+    public void setId(Long id) 
+    {
+        this.id = id;
+    }
+
+    public Long getId() 
+    {
+        return id;
+    }
+    public void setNode(String node) 
+    {
+        this.node = node;
+    }
+
+    public String getNode() 
+    {
+        return node;
+    }
+    public void setSysTypes(String sysTypes) 
+    {
+        this.sysTypes = sysTypes;
+    }
+
+    public String getSysTypes() 
+    {
+        return sysTypes;
+    }
+    public void setSubscribe(String subscribe) 
+    {
+        this.subscribe = subscribe;
+    }
+
+    public String getSubscribe() 
+    {
+        return subscribe;
+    }
+    public void setrFunction(String rFunction) 
+    {
+        this.rFunction = rFunction;
+    }
+
+    public String getrFunction() 
+    {
+        return rFunction;
+    }
+    public void setRemarks(String remarks) 
+    {
+        this.remarks = remarks;
+    }
+
+    public String getRemarks() 
+    {
+        return remarks;
+    }
+    public void setProcessName(String processName) 
+    {
+        this.processName = processName;
+    }
+
+    public String getProcessName() 
+    {
+        return processName;
+    }
+    public void setProcess(String process) 
+    {
+        this.process = process;
+    }
+
+    public String getProcess() 
+    {
+        return process;
+    }
+    public void setState(Long state) 
+    {
+        this.state = state;
+    }
+
+    public Long getState() 
+    {
+        return state;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("node", getNode())
+            .append("sysTypes", getSysTypes())
+            .append("subscribe", getSubscribe())
+            .append("rFunction", getrFunction())
+            .append("remarks", getRemarks())
+            .append("processName", getProcessName())
+            .append("process", getProcess())
+            .append("state", getState())
+            .toString();
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/domain/NodeEntity.java b/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/domain/NodeEntity.java
new file mode 100644
index 0000000..8d4ba5d
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/domain/NodeEntity.java
@@ -0,0 +1,19 @@
+package com.jcdm.main.da.opcuaconfig.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder(toBuilder = true)
+@AllArgsConstructor
+@NoArgsConstructor
+public class NodeEntity {
+
+	private Integer index;
+	private String identifier;
+	private Object value;
+	private String type;
+	private Integer clientHandle;
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/init/BeanUtils.java b/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/init/BeanUtils.java
new file mode 100644
index 0000000..b61e3b5
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/init/BeanUtils.java
@@ -0,0 +1,30 @@
+package com.jcdm.main.da.opcuaconfig.init;
+
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+
+@Component
+public class BeanUtils implements ApplicationContextAware {
+    protected static ApplicationContext applicationContext ;
+
+    @Override
+    public void setApplicationContext(ApplicationContext arg0) throws BeansException {
+        if (applicationContext == null) {
+            applicationContext = arg0;
+        }
+
+    }
+    public static Object getBean(String name) {
+        //name琛ㄧず鍏朵粬瑕佹敞鍏ョ殑娉ㄨВname鍚�
+        return applicationContext.getBean(name);
+    }
+
+    /**
+     * 鎷垮埌ApplicationContext瀵硅薄瀹炰緥鍚庡氨鍙互鎵嬪姩鑾峰彇Bean鐨勬敞鍏ュ疄渚嬪璞�
+     */
+    public static <T> T getBean(Class<T> clazz) {
+        return applicationContext.getBean(clazz);
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/init/OpcusConfigInit.java b/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/init/OpcusConfigInit.java
new file mode 100644
index 0000000..2404567
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/init/OpcusConfigInit.java
@@ -0,0 +1,48 @@
+package com.jcdm.main.da.opcuaconfig.init;
+
+import com.google.common.collect.Lists;
+import com.jcdm.main.da.opcuaconfig.client.ClientHandler;
+import com.jcdm.main.da.opcuaconfig.domain.DaOpcuaConfig;
+import com.jcdm.main.da.opcuaconfig.domain.NodeEntity;
+import com.jcdm.main.da.opcuaconfig.service.IDaOpcuaConfigService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+@Component
+@Slf4j
+public class OpcusConfigInit implements CommandLineRunner {
+
+    @Autowired
+    private ClientHandler clientHandler;
+
+    @Autowired
+    private IDaOpcuaConfigService daOpcuaConfigService;
+
+    @Override
+    public void run(String... args) throws Exception {
+        try {
+            DaOpcuaConfig daOpcuaConfig=new DaOpcuaConfig();
+            daOpcuaConfig.setSubscribe("Y"); //璁剧疆鏌ヨ鏉′欢锛屾槸鍚﹁闃呯姸鎬佷负Y鐨勬墍鏈夋暟鎹�.
+            List<DaOpcuaConfig> nodeslist=daOpcuaConfigService.selectDaOpcuaConfigList(daOpcuaConfig);
+            clientHandler.connect();
+            if (nodeslist != null && nodeslist.size() > 0) {
+                List<NodeEntity> NodeList = Lists.transform(nodeslist, (DaOpcuaConfig) -> {
+                    NodeEntity nodeEntity = new NodeEntity();
+                    nodeEntity.setIndex(2);
+                    nodeEntity.setIdentifier(DaOpcuaConfig.getNode());
+                    return nodeEntity;
+                });
+                clientHandler.subscribe(NodeList);
+                log.info("鍒濆鍖朞PC璁㈤槄" + nodeslist.size() + "鏉★紒");
+            }
+            log.info("绯荤粺鎻愮ず锛孫PCUA璁㈤槄鎴愬姛锛�");
+        } catch (Exception e) {
+            e.printStackTrace();
+            log.info("绯荤粺鎻愮ず锛孫PCUA璁㈤槄澶辫触锛�");
+        }
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/init/Properties.java b/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/init/Properties.java
new file mode 100644
index 0000000..fc06c6b
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/init/Properties.java
@@ -0,0 +1,57 @@
+/**
+ * Created by Jellyleo on 2019骞�12鏈�19鏃�
+ * Copyright 漏 2019 jellyleo.com 
+ * All rights reserved. 
+ */
+package com.jcdm.main.da.opcuaconfig.init;
+
+import lombok.Getter;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
+
+/**
+ * @ClassName: Properties
+ * @Description: OpcUa鍙傛暟
+ * @author yyt
+ * @date 2023骞�10鏈�13鏃�
+ */
+@Getter
+@Configuration
+@PropertySource("classpath:opcua.properties")
+public class Properties {
+	@Value("${opcua.server.endpoint.url}")
+	private String endpointUrl;
+	@Value("${opcua.server.idp.username}")
+	private String idpUsername;
+	@Value("${opcua.server.idp.password}")
+	private String idpPassword;
+	@Value("${opcua.client.app.name}")
+	private String appName;
+	@Value("${opcua.client.app.uri}")
+	private String appUri;
+	@Value("${opcua.client.cert.path}")
+	private String certPath;
+	@Value("${opcua.client.cert.file}")
+	private String certFile;
+	@Value("${opcua.client.cert.alias}")
+	private String certAlias;
+	@Value("${opcua.client.cert.common.name}")
+	private String commonName;
+	@Value("${opcua.client.cert.organization}")
+	private String organization;
+	@Value("${opcua.client.cert.organization.unit}")
+	private String orgUnit;
+	@Value("${opcua.client.cert.locality.name}")
+	private String localityName;
+	@Value("${opcua.client.cert.state.name}")
+	private String stateName;
+	@Value("${opcua.client.cert.country.code}")
+	private String countryCode;
+	@Value("${opcua.client.cert.dns.name}")
+	private String dnsName;
+	@Value("${opcua.client.cert.ip.address}")
+	private String ipAddress;
+	@Value("${opcua.client.cert.keystore.password}")
+	private String keyPassword;
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/mapper/DaOpcuaConfigMapper.java b/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/mapper/DaOpcuaConfigMapper.java
new file mode 100644
index 0000000..7feb41d
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/mapper/DaOpcuaConfigMapper.java
@@ -0,0 +1,62 @@
+package com.jcdm.main.da.opcuaconfig.mapper;
+
+import com.jcdm.main.da.opcuaconfig.domain.DaOpcuaConfig;
+
+import java.util.List;
+
+/**
+ * 浜や簰淇″彿閰嶇疆Mapper鎺ュ彛
+ * 
+ * @author yyt
+ * @date 2024-01-23
+ */
+public interface DaOpcuaConfigMapper 
+{
+    /**
+     * 鏌ヨ浜や簰淇″彿閰嶇疆
+     * 
+     * @param id 浜や簰淇″彿閰嶇疆涓婚敭
+     * @return 浜や簰淇″彿閰嶇疆
+     */
+    public DaOpcuaConfig selectDaOpcuaConfigById(Long id);
+
+    /**
+     * 鏌ヨ浜や簰淇″彿閰嶇疆鍒楄〃
+     * 
+     * @param daOpcuaConfig 浜や簰淇″彿閰嶇疆
+     * @return 浜や簰淇″彿閰嶇疆闆嗗悎
+     */
+    public List<DaOpcuaConfig> selectDaOpcuaConfigList(DaOpcuaConfig daOpcuaConfig);
+
+    /**
+     * 鏂板浜や簰淇″彿閰嶇疆
+     * 
+     * @param daOpcuaConfig 浜や簰淇″彿閰嶇疆
+     * @return 缁撴灉
+     */
+    public int insertDaOpcuaConfig(DaOpcuaConfig daOpcuaConfig);
+
+    /**
+     * 淇敼浜や簰淇″彿閰嶇疆
+     * 
+     * @param daOpcuaConfig 浜や簰淇″彿閰嶇疆
+     * @return 缁撴灉
+     */
+    public int updateDaOpcuaConfig(DaOpcuaConfig daOpcuaConfig);
+
+    /**
+     * 鍒犻櫎浜や簰淇″彿閰嶇疆
+     * 
+     * @param id 浜や簰淇″彿閰嶇疆涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteDaOpcuaConfigById(Long id);
+
+    /**
+     * 鎵归噺鍒犻櫎浜や簰淇″彿閰嶇疆
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteDaOpcuaConfigByIds(Long[] ids);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/service/IDaOpcuaConfigService.java b/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/service/IDaOpcuaConfigService.java
new file mode 100644
index 0000000..13fbdfa
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/service/IDaOpcuaConfigService.java
@@ -0,0 +1,62 @@
+package com.jcdm.main.da.opcuaconfig.service;
+
+import com.jcdm.main.da.opcuaconfig.domain.DaOpcuaConfig;
+
+import java.util.List;
+
+/**
+ * 浜や簰淇″彿閰嶇疆Service鎺ュ彛
+ * 
+ * @author yyt
+ * @date 2024-01-23
+ */
+public interface IDaOpcuaConfigService 
+{
+    /**
+     * 鏌ヨ浜や簰淇″彿閰嶇疆
+     * 
+     * @param id 浜や簰淇″彿閰嶇疆涓婚敭
+     * @return 浜や簰淇″彿閰嶇疆
+     */
+    public DaOpcuaConfig selectDaOpcuaConfigById(Long id);
+
+    /**
+     * 鏌ヨ浜や簰淇″彿閰嶇疆鍒楄〃
+     * 
+     * @param daOpcuaConfig 浜や簰淇″彿閰嶇疆
+     * @return 浜や簰淇″彿閰嶇疆闆嗗悎
+     */
+    public List<DaOpcuaConfig> selectDaOpcuaConfigList(DaOpcuaConfig daOpcuaConfig);
+
+    /**
+     * 鏂板浜や簰淇″彿閰嶇疆
+     * 
+     * @param daOpcuaConfig 浜や簰淇″彿閰嶇疆
+     * @return 缁撴灉
+     */
+    public int insertDaOpcuaConfig(DaOpcuaConfig daOpcuaConfig);
+
+    /**
+     * 淇敼浜や簰淇″彿閰嶇疆
+     * 
+     * @param daOpcuaConfig 浜や簰淇″彿閰嶇疆
+     * @return 缁撴灉
+     */
+    public int updateDaOpcuaConfig(DaOpcuaConfig daOpcuaConfig);
+
+    /**
+     * 鎵归噺鍒犻櫎浜や簰淇″彿閰嶇疆
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑浜や簰淇″彿閰嶇疆涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteDaOpcuaConfigByIds(Long[] ids);
+
+    /**
+     * 鍒犻櫎浜や簰淇″彿閰嶇疆淇℃伅
+     * 
+     * @param id 浜や簰淇″彿閰嶇疆涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteDaOpcuaConfigById(Long id);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/service/impl/DaOpcuaConfigServiceImpl.java b/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/service/impl/DaOpcuaConfigServiceImpl.java
new file mode 100644
index 0000000..02e9c42
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/service/impl/DaOpcuaConfigServiceImpl.java
@@ -0,0 +1,94 @@
+package com.jcdm.main.da.opcuaconfig.service.impl;
+
+import com.jcdm.main.da.opcuaconfig.domain.DaOpcuaConfig;
+import com.jcdm.main.da.opcuaconfig.mapper.DaOpcuaConfigMapper;
+import com.jcdm.main.da.opcuaconfig.service.IDaOpcuaConfigService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 浜や簰淇″彿閰嶇疆Service涓氬姟灞傚鐞�
+ * 
+ * @author yyt
+ * @date 2024-01-23
+ */
+@Service
+public class DaOpcuaConfigServiceImpl implements IDaOpcuaConfigService
+{
+    @Autowired
+    private DaOpcuaConfigMapper daOpcuaConfigMapper;
+
+    /**
+     * 鏌ヨ浜や簰淇″彿閰嶇疆
+     * 
+     * @param id 浜や簰淇″彿閰嶇疆涓婚敭
+     * @return 浜や簰淇″彿閰嶇疆
+     */
+    @Override
+    public DaOpcuaConfig selectDaOpcuaConfigById(Long id)
+    {
+        return daOpcuaConfigMapper.selectDaOpcuaConfigById(id);
+    }
+
+    /**
+     * 鏌ヨ浜や簰淇″彿閰嶇疆鍒楄〃
+     * 
+     * @param daOpcuaConfig 浜や簰淇″彿閰嶇疆
+     * @return 浜や簰淇″彿閰嶇疆
+     */
+    @Override
+    public List<DaOpcuaConfig> selectDaOpcuaConfigList(DaOpcuaConfig daOpcuaConfig)
+    {
+        return daOpcuaConfigMapper.selectDaOpcuaConfigList(daOpcuaConfig);
+    }
+
+    /**
+     * 鏂板浜や簰淇″彿閰嶇疆
+     * 
+     * @param daOpcuaConfig 浜や簰淇″彿閰嶇疆
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertDaOpcuaConfig(DaOpcuaConfig daOpcuaConfig)
+    {
+        return daOpcuaConfigMapper.insertDaOpcuaConfig(daOpcuaConfig);
+    }
+
+    /**
+     * 淇敼浜や簰淇″彿閰嶇疆
+     * 
+     * @param daOpcuaConfig 浜や簰淇″彿閰嶇疆
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateDaOpcuaConfig(DaOpcuaConfig daOpcuaConfig)
+    {
+        return daOpcuaConfigMapper.updateDaOpcuaConfig(daOpcuaConfig);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎浜や簰淇″彿閰嶇疆
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑浜や簰淇″彿閰嶇疆涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteDaOpcuaConfigByIds(Long[] ids)
+    {
+        return daOpcuaConfigMapper.deleteDaOpcuaConfigByIds(ids);
+    }
+
+    /**
+     * 鍒犻櫎浜や簰淇″彿閰嶇疆淇℃伅
+     * 
+     * @param id 浜や簰淇″彿閰嶇疆涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteDaOpcuaConfigById(Long id)
+    {
+        return daOpcuaConfigMapper.deleteDaOpcuaConfigById(id);
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/da/paramCollection/controller/DaParamCollectionController.java b/jcdm-main/src/main/java/com/jcdm/main/da/paramCollection/controller/DaParamCollectionController.java
new file mode 100644
index 0000000..082011e
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/da/paramCollection/controller/DaParamCollectionController.java
@@ -0,0 +1,103 @@
+package com.jcdm.main.da.paramCollection.controller;
+
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.core.page.TableDataInfo;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.common.utils.DateUtils;
+import com.jcdm.common.utils.poi.ExcelUtil;
+import com.jcdm.main.da.paramCollection.domain.DaParamCollection;
+import com.jcdm.main.da.paramCollection.service.IDaParamCollectionService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+
+/**
+ * 璁惧浜у搧杩囩▼鍙傛暟閲囬泦Controller
+ * 
+ * @author yyt
+ * @date 2023-12-13
+ */
+@RestController
+@RequestMapping("/main/paramCollection")
+public class DaParamCollectionController extends BaseController
+{
+    @Autowired
+    private IDaParamCollectionService daParamCollectionService;
+
+    /**
+     * 鏌ヨ璁惧浜у搧杩囩▼鍙傛暟閲囬泦鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('main:paramCollection:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(DaParamCollection daParamCollection)
+    {
+        startPage();
+        List<DaParamCollection> list = daParamCollectionService.selectDaParamCollectionList(daParamCollection);
+        return getDataTable(list);
+    }
+
+    /**
+     * 瀵煎嚭璁惧浜у搧杩囩▼鍙傛暟閲囬泦鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('main:paramCollection:export')")
+    @Log(title = "璁惧浜у搧杩囩▼鍙傛暟閲囬泦", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, DaParamCollection daParamCollection)
+    {
+        List<DaParamCollection> list = daParamCollectionService.selectDaParamCollectionList(daParamCollection);
+        ExcelUtil<DaParamCollection> util = new ExcelUtil<DaParamCollection>(DaParamCollection.class);
+        util.exportExcel(response, list, "璁惧浜у搧杩囩▼鍙傛暟閲囬泦鏁版嵁");
+    }
+
+    /**
+     * 鑾峰彇璁惧浜у搧杩囩▼鍙傛暟閲囬泦璇︾粏淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('main:paramCollection:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(daParamCollectionService.selectDaParamCollectionById(id));
+    }
+
+    /**
+     * 鏂板璁惧浜у搧杩囩▼鍙傛暟閲囬泦
+     */
+    @PreAuthorize("@ss.hasPermi('main:paramCollection:add')")
+    @Log(title = "璁惧浜у搧杩囩▼鍙傛暟閲囬泦", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody DaParamCollection daParamCollection)
+    {
+        daParamCollection.setCreateBy(getUsername());
+        daParamCollection.setCreateTime(DateUtils.getNowDate());
+        return toAjax(daParamCollectionService.insertDaParamCollection(daParamCollection));
+    }
+
+    /**
+     * 淇敼璁惧浜у搧杩囩▼鍙傛暟閲囬泦
+     */
+    @PreAuthorize("@ss.hasPermi('main:paramCollection:edit')")
+    @Log(title = "璁惧浜у搧杩囩▼鍙傛暟閲囬泦", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody DaParamCollection daParamCollection)
+    {
+        daParamCollection.setUpdateBy(getUsername());
+        daParamCollection.setUpdateTime(DateUtils.getNowDate());
+        return toAjax(daParamCollectionService.updateDaParamCollection(daParamCollection));
+    }
+
+    /**
+     * 鍒犻櫎璁惧浜у搧杩囩▼鍙傛暟閲囬泦
+     */
+    @PreAuthorize("@ss.hasPermi('main:paramCollection:remove')")
+    @Log(title = "璁惧浜у搧杩囩▼鍙傛暟閲囬泦", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(daParamCollectionService.deleteDaParamCollectionByIds(ids));
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/da/paramCollection/domain/DaParamCollection.java b/jcdm-main/src/main/java/com/jcdm/main/da/paramCollection/domain/DaParamCollection.java
new file mode 100644
index 0000000..05d7528
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/da/paramCollection/domain/DaParamCollection.java
@@ -0,0 +1,317 @@
+package com.jcdm.main.da.paramCollection.domain;
+
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.core.domain.BaseEntity;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+import java.util.Date;
+
+/**
+ * 璁惧浜у搧杩囩▼鍙傛暟閲囬泦瀵硅薄 da_param_collection
+ * 
+ * @author yyt
+ * @date 2023-12-13
+ */
+public class DaParamCollection extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 涓婚敭id */
+    private Long id;
+
+    /** 宸ュ崟缂栧彿 */
+    @Excel(name = "宸ュ崟缂栧彿")
+    private String workOrderNo;
+
+    /** 鎬绘垚搴忓垪鍙� */
+    @Excel(name = "鎬绘垚搴忓垪鍙�")
+    private String sfcCode;
+
+    /** 浜у搧缂栧彿 */
+    @Excel(name = "浜у搧缂栧彿")
+    private String productCode;
+
+    /** 浜х嚎缂栧彿 */
+    @Excel(name = "浜х嚎缂栧彿")
+    private String productionLine;
+
+    /** 宸ヤ綅缂栧彿 */
+    @Excel(name = "宸ヤ綅缂栧彿")
+    private String locationCode;
+
+    /** 璁惧缂栧彿 */
+    @Excel(name = "璁惧缂栧彿")
+    private String equipmentNo;
+
+    /** 鍙傛暟缂栫爜 */
+    @Excel(name = "鍙傛暟缂栫爜")
+    private String paramCode;
+
+    /** 鍙傛暟鍊� */
+    @Excel(name = "鍙傛暟鍊�")
+    private String paramValue;
+
+    /** 鍙傛暟涓婇檺 */
+    @Excel(name = "鍙傛暟涓婇檺")
+    private String paramUpper;
+
+    /** 鍙傛暟涓嬮檺 */
+    @Excel(name = "鍙傛暟涓嬮檺")
+    private String paramLower;
+
+    /** 鏍囧噯鍊� */
+    @Excel(name = "鏍囧噯鍊�")
+    private String paramStandard;
+
+    /** 閲囬泦鏃堕棿 */
+    @Excel(name = "閲囬泦鏃堕棿")
+    private Date collectionTime;
+
+    /** 棰勭暀瀛楁1 */
+    private String spareField1;
+
+    /** 棰勭暀瀛楁2 */
+    private String spareField2;
+
+    /** 鍒涘缓鐢ㄦ埛 */
+    private String createUser;
+
+    /** 鏇存敼鐢ㄦ埛 */
+    private String updateUser;
+
+    /** 鐘舵�侊紙1鍚堟牸銆�2涓嶅悎鏍硷級 */
+    @Excel(name = "鐘舵��", readConverterExp = "1=鍚堟牸銆�2涓嶅悎鏍�")
+    private String state;
+
+    /** 鍙傛暟鍚嶇О */
+    @Excel(name = "鍙傛暟鍚嶇О")
+    private String paramName;
+
+    /** 鍗曚綅 */
+    @Excel(name = "鍗曚綅")
+    private String unit;
+
+    /** 绫诲瀷 */
+    @Excel(name = "绫诲瀷")
+    private String type;
+
+    public void setId(Long id) 
+    {
+        this.id = id;
+    }
+
+    public Long getId() 
+    {
+        return id;
+    }
+    public void setWorkOrderNo(String workOrderNo) 
+    {
+        this.workOrderNo = workOrderNo;
+    }
+
+    public String getWorkOrderNo() 
+    {
+        return workOrderNo;
+    }
+    public void setSfcCode(String sfcCode) 
+    {
+        this.sfcCode = sfcCode;
+    }
+
+    public String getSfcCode() 
+    {
+        return sfcCode;
+    }
+    public void setProductCode(String productCode) 
+    {
+        this.productCode = productCode;
+    }
+
+    public String getProductCode() 
+    {
+        return productCode;
+    }
+    public void setProductionLine(String productionLine) 
+    {
+        this.productionLine = productionLine;
+    }
+
+    public String getProductionLine() 
+    {
+        return productionLine;
+    }
+    public void setLocationCode(String locationCode) 
+    {
+        this.locationCode = locationCode;
+    }
+
+    public String getLocationCode() 
+    {
+        return locationCode;
+    }
+    public void setEquipmentNo(String equipmentNo) 
+    {
+        this.equipmentNo = equipmentNo;
+    }
+
+    public String getEquipmentNo() 
+    {
+        return equipmentNo;
+    }
+    public void setParamCode(String paramCode) 
+    {
+        this.paramCode = paramCode;
+    }
+
+    public String getParamCode() 
+    {
+        return paramCode;
+    }
+    public void setParamValue(String paramValue) 
+    {
+        this.paramValue = paramValue;
+    }
+
+    public String getParamValue() 
+    {
+        return paramValue;
+    }
+    public void setParamUpper(String paramUpper) 
+    {
+        this.paramUpper = paramUpper;
+    }
+
+    public String getParamUpper() 
+    {
+        return paramUpper;
+    }
+    public void setParamLower(String paramLower) 
+    {
+        this.paramLower = paramLower;
+    }
+
+    public String getParamLower() 
+    {
+        return paramLower;
+    }
+    public void setParamStandard(String paramStandard) 
+    {
+        this.paramStandard = paramStandard;
+    }
+
+    public String getParamStandard() 
+    {
+        return paramStandard;
+    }
+    public void setCollectionTime(Date collectionTime) 
+    {
+        this.collectionTime = collectionTime;
+    }
+
+    public Date getCollectionTime() 
+    {
+        return collectionTime;
+    }
+    public void setSpareField1(String spareField1) 
+    {
+        this.spareField1 = spareField1;
+    }
+
+    public String getSpareField1() 
+    {
+        return spareField1;
+    }
+    public void setSpareField2(String spareField2) 
+    {
+        this.spareField2 = spareField2;
+    }
+
+    public String getSpareField2() 
+    {
+        return spareField2;
+    }
+    public void setCreateUser(String createUser) 
+    {
+        this.createUser = createUser;
+    }
+
+    public String getCreateUser() 
+    {
+        return createUser;
+    }
+    public void setUpdateUser(String updateUser) 
+    {
+        this.updateUser = updateUser;
+    }
+
+    public String getUpdateUser() 
+    {
+        return updateUser;
+    }
+    public void setState(String state) 
+    {
+        this.state = state;
+    }
+
+    public String getState() 
+    {
+        return state;
+    }
+    public void setParamName(String paramName) 
+    {
+        this.paramName = paramName;
+    }
+
+    public String getParamName() 
+    {
+        return paramName;
+    }
+    public void setUnit(String unit) 
+    {
+        this.unit = unit;
+    }
+
+    public String getUnit() 
+    {
+        return unit;
+    }
+    public void setType(String type) 
+    {
+        this.type = type;
+    }
+
+    public String getType() 
+    {
+        return type;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("workOrderNo", getWorkOrderNo())
+            .append("sfcCode", getSfcCode())
+            .append("productCode", getProductCode())
+            .append("productionLine", getProductionLine())
+            .append("locationCode", getLocationCode())
+            .append("equipmentNo", getEquipmentNo())
+            .append("paramCode", getParamCode())
+            .append("paramValue", getParamValue())
+            .append("paramUpper", getParamUpper())
+            .append("paramLower", getParamLower())
+            .append("paramStandard", getParamStandard())
+            .append("collectionTime", getCollectionTime())
+            .append("spareField1", getSpareField1())
+            .append("spareField2", getSpareField2())
+            .append("createUser", getCreateUser())
+            .append("createTime", getCreateTime())
+            .append("updateUser", getUpdateUser())
+            .append("updateTime", getUpdateTime())
+            .append("state", getState())
+            .append("paramName", getParamName())
+            .append("unit", getUnit())
+            .append("type", getType())
+            .toString();
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/da/paramCollection/mapper/DaParamCollectionMapper.java b/jcdm-main/src/main/java/com/jcdm/main/da/paramCollection/mapper/DaParamCollectionMapper.java
new file mode 100644
index 0000000..6503fbe
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/da/paramCollection/mapper/DaParamCollectionMapper.java
@@ -0,0 +1,62 @@
+package com.jcdm.main.da.paramCollection.mapper;
+
+import com.jcdm.main.da.paramCollection.domain.DaParamCollection;
+
+import java.util.List;
+
+/**
+ * 璁惧浜у搧杩囩▼鍙傛暟閲囬泦Mapper鎺ュ彛
+ * 
+ * @author yyt
+ * @date 2023-12-13
+ */
+public interface DaParamCollectionMapper 
+{
+    /**
+     * 鏌ヨ璁惧浜у搧杩囩▼鍙傛暟閲囬泦
+     * 
+     * @param id 璁惧浜у搧杩囩▼鍙傛暟閲囬泦涓婚敭
+     * @return 璁惧浜у搧杩囩▼鍙傛暟閲囬泦
+     */
+    public DaParamCollection selectDaParamCollectionById(Long id);
+
+    /**
+     * 鏌ヨ璁惧浜у搧杩囩▼鍙傛暟閲囬泦鍒楄〃
+     * 
+     * @param daParamCollection 璁惧浜у搧杩囩▼鍙傛暟閲囬泦
+     * @return 璁惧浜у搧杩囩▼鍙傛暟閲囬泦闆嗗悎
+     */
+    public List<DaParamCollection> selectDaParamCollectionList(DaParamCollection daParamCollection);
+
+    /**
+     * 鏂板璁惧浜у搧杩囩▼鍙傛暟閲囬泦
+     * 
+     * @param daParamCollection 璁惧浜у搧杩囩▼鍙傛暟閲囬泦
+     * @return 缁撴灉
+     */
+    public int insertDaParamCollection(DaParamCollection daParamCollection);
+
+    /**
+     * 淇敼璁惧浜у搧杩囩▼鍙傛暟閲囬泦
+     * 
+     * @param daParamCollection 璁惧浜у搧杩囩▼鍙傛暟閲囬泦
+     * @return 缁撴灉
+     */
+    public int updateDaParamCollection(DaParamCollection daParamCollection);
+
+    /**
+     * 鍒犻櫎璁惧浜у搧杩囩▼鍙傛暟閲囬泦
+     * 
+     * @param id 璁惧浜у搧杩囩▼鍙傛暟閲囬泦涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteDaParamCollectionById(Long id);
+
+    /**
+     * 鎵归噺鍒犻櫎璁惧浜у搧杩囩▼鍙傛暟閲囬泦
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteDaParamCollectionByIds(Long[] ids);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/da/paramCollection/service/IDaParamCollectionService.java b/jcdm-main/src/main/java/com/jcdm/main/da/paramCollection/service/IDaParamCollectionService.java
new file mode 100644
index 0000000..95c23fe
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/da/paramCollection/service/IDaParamCollectionService.java
@@ -0,0 +1,62 @@
+package com.jcdm.main.da.paramCollection.service;
+
+import com.jcdm.main.da.paramCollection.domain.DaParamCollection;
+
+import java.util.List;
+
+/**
+ * 璁惧浜у搧杩囩▼鍙傛暟閲囬泦Service鎺ュ彛
+ * 
+ * @author yyt
+ * @date 2023-12-13
+ */
+public interface IDaParamCollectionService 
+{
+    /**
+     * 鏌ヨ璁惧浜у搧杩囩▼鍙傛暟閲囬泦
+     * 
+     * @param id 璁惧浜у搧杩囩▼鍙傛暟閲囬泦涓婚敭
+     * @return 璁惧浜у搧杩囩▼鍙傛暟閲囬泦
+     */
+    public DaParamCollection selectDaParamCollectionById(Long id);
+
+    /**
+     * 鏌ヨ璁惧浜у搧杩囩▼鍙傛暟閲囬泦鍒楄〃
+     * 
+     * @param daParamCollection 璁惧浜у搧杩囩▼鍙傛暟閲囬泦
+     * @return 璁惧浜у搧杩囩▼鍙傛暟閲囬泦闆嗗悎
+     */
+    public List<DaParamCollection> selectDaParamCollectionList(DaParamCollection daParamCollection);
+
+    /**
+     * 鏂板璁惧浜у搧杩囩▼鍙傛暟閲囬泦
+     * 
+     * @param daParamCollection 璁惧浜у搧杩囩▼鍙傛暟閲囬泦
+     * @return 缁撴灉
+     */
+    public int insertDaParamCollection(DaParamCollection daParamCollection);
+
+    /**
+     * 淇敼璁惧浜у搧杩囩▼鍙傛暟閲囬泦
+     * 
+     * @param daParamCollection 璁惧浜у搧杩囩▼鍙傛暟閲囬泦
+     * @return 缁撴灉
+     */
+    public int updateDaParamCollection(DaParamCollection daParamCollection);
+
+    /**
+     * 鎵归噺鍒犻櫎璁惧浜у搧杩囩▼鍙傛暟閲囬泦
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑璁惧浜у搧杩囩▼鍙傛暟閲囬泦涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteDaParamCollectionByIds(Long[] ids);
+
+    /**
+     * 鍒犻櫎璁惧浜у搧杩囩▼鍙傛暟閲囬泦淇℃伅
+     * 
+     * @param id 璁惧浜у搧杩囩▼鍙傛暟閲囬泦涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteDaParamCollectionById(Long id);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/da/paramCollection/service/impl/DaParamCollectionServiceImpl.java b/jcdm-main/src/main/java/com/jcdm/main/da/paramCollection/service/impl/DaParamCollectionServiceImpl.java
new file mode 100644
index 0000000..54b40a6
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/da/paramCollection/service/impl/DaParamCollectionServiceImpl.java
@@ -0,0 +1,97 @@
+package com.jcdm.main.da.paramCollection.service.impl;
+
+import com.jcdm.common.utils.DateUtils;
+import com.jcdm.main.da.paramCollection.domain.DaParamCollection;
+import com.jcdm.main.da.paramCollection.mapper.DaParamCollectionMapper;
+import com.jcdm.main.da.paramCollection.service.IDaParamCollectionService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 璁惧浜у搧杩囩▼鍙傛暟閲囬泦Service涓氬姟灞傚鐞�
+ * 
+ * @author yyt
+ * @date 2023-12-13
+ */
+@Service
+public class DaParamCollectionServiceImpl implements IDaParamCollectionService
+{
+    @Autowired
+    private DaParamCollectionMapper daParamCollectionMapper;
+
+    /**
+     * 鏌ヨ璁惧浜у搧杩囩▼鍙傛暟閲囬泦
+     * 
+     * @param id 璁惧浜у搧杩囩▼鍙傛暟閲囬泦涓婚敭
+     * @return 璁惧浜у搧杩囩▼鍙傛暟閲囬泦
+     */
+    @Override
+    public DaParamCollection selectDaParamCollectionById(Long id)
+    {
+        return daParamCollectionMapper.selectDaParamCollectionById(id);
+    }
+
+    /**
+     * 鏌ヨ璁惧浜у搧杩囩▼鍙傛暟閲囬泦鍒楄〃
+     * 
+     * @param daParamCollection 璁惧浜у搧杩囩▼鍙傛暟閲囬泦
+     * @return 璁惧浜у搧杩囩▼鍙傛暟閲囬泦
+     */
+    @Override
+    public List<DaParamCollection> selectDaParamCollectionList(DaParamCollection daParamCollection)
+    {
+        return daParamCollectionMapper.selectDaParamCollectionList(daParamCollection);
+    }
+
+    /**
+     * 鏂板璁惧浜у搧杩囩▼鍙傛暟閲囬泦
+     * 
+     * @param daParamCollection 璁惧浜у搧杩囩▼鍙傛暟閲囬泦
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertDaParamCollection(DaParamCollection daParamCollection)
+    {
+        daParamCollection.setCreateTime(DateUtils.getNowDate());
+        return daParamCollectionMapper.insertDaParamCollection(daParamCollection);
+    }
+
+    /**
+     * 淇敼璁惧浜у搧杩囩▼鍙傛暟閲囬泦
+     * 
+     * @param daParamCollection 璁惧浜у搧杩囩▼鍙傛暟閲囬泦
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateDaParamCollection(DaParamCollection daParamCollection)
+    {
+        daParamCollection.setUpdateTime(DateUtils.getNowDate());
+        return daParamCollectionMapper.updateDaParamCollection(daParamCollection);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎璁惧浜у搧杩囩▼鍙傛暟閲囬泦
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑璁惧浜у搧杩囩▼鍙傛暟閲囬泦涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteDaParamCollectionByIds(Long[] ids)
+    {
+        return daParamCollectionMapper.deleteDaParamCollectionByIds(ids);
+    }
+
+    /**
+     * 鍒犻櫎璁惧浜у搧杩囩▼鍙傛暟閲囬泦淇℃伅
+     * 
+     * @param id 璁惧浜у搧杩囩▼鍙傛暟閲囬泦涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteDaParamCollectionById(Long id)
+    {
+        return daParamCollectionMapper.deleteDaParamCollectionById(id);
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/common/Constants.java b/jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/common/Constants.java
new file mode 100644
index 0000000..5b0d40e
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/common/Constants.java
@@ -0,0 +1,5 @@
+package com.jcdm.main.da.passingStationCollection.common;
+
+public final class Constants {
+
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/controller/DaPassingStationCollectionController.java b/jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/controller/DaPassingStationCollectionController.java
new file mode 100644
index 0000000..4e655a7
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/controller/DaPassingStationCollectionController.java
@@ -0,0 +1,133 @@
+package com.jcdm.main.da.passingStationCollection.controller;
+
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.core.domain.R;
+import com.jcdm.common.core.page.TableDataInfo;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.common.utils.DateUtils;
+import com.jcdm.common.utils.poi.ExcelUtil;
+import com.jcdm.main.da.passingStationCollection.domain.DaPassingStationCollection;
+import com.jcdm.main.da.passingStationCollection.service.IDaPassingStationCollectionService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+
+/**
+ * 浜у搧杩囩珯閲囬泦Controller
+ * 
+ * @author yyt
+ * @date 2023-12-12
+ */
+@RestController
+@RequestMapping("/da/passingStationCollection")
+public class DaPassingStationCollectionController extends BaseController
+{
+    @Autowired
+    private IDaPassingStationCollectionService daPassingStationCollectionService;
+
+    /**
+     * 鏌ヨ浜у搧杩囩珯閲囬泦鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('da:passingStationCollection:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(DaPassingStationCollection daPassingStationCollection)
+    {
+        startPage();
+        List<DaPassingStationCollection> list = daPassingStationCollectionService.selectDaPassingStationCollectionList(daPassingStationCollection);
+        return getDataTable(list);
+    }
+
+    /**
+     * 鏌ヨ浜у搧杩囩珯閲囬泦鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('da:passingStationCollection:list')")
+    @GetMapping("/noPageList")
+    public TableDataInfo noPageList(DaPassingStationCollection daPassingStationCollection)
+    {
+        List<DaPassingStationCollection> list = daPassingStationCollectionService.selectDaPassingStationCollectionList(daPassingStationCollection);
+        return getDataTable(list);
+    }
+
+//    @PreAuthorize("@ss.hasPermi('da:passingStationCollection:list')")
+//    @GetMapping("/getProduceNumToday")
+//    public R getProduceNumToday(String fieldName)
+//    {
+//        Integer num = daPassingStationCollectionService.getProduceNumToday(fieldName);
+//        return R.ok(num);
+//    }
+
+    /**
+     * 鏌ヨ浜у搧杩囩珯閲囬泦鍒楄〃
+     */
+    @GetMapping("/insertRepairRecordByIds")
+    public AjaxResult insertRepairRecordByIds(DaPassingStationCollection daPassingStationCollection)
+    {
+        daPassingStationCollectionService.insertRepairRecordByIds(daPassingStationCollection);
+        return AjaxResult.success();
+    }
+
+    /**
+     * 瀵煎嚭浜у搧杩囩珯閲囬泦鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('da:passingStationCollection:export')")
+    @Log(title = "浜у搧杩囩珯閲囬泦", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, DaPassingStationCollection daPassingStationCollection)
+    {
+        List<DaPassingStationCollection> list = daPassingStationCollectionService.selectDaPassingStationCollectionList(daPassingStationCollection);
+        ExcelUtil<DaPassingStationCollection> util = new ExcelUtil<DaPassingStationCollection>(DaPassingStationCollection.class);
+        util.exportExcel(response, list, "浜у搧杩囩珯閲囬泦鏁版嵁");
+    }
+
+    /**
+     * 鑾峰彇浜у搧杩囩珯閲囬泦璇︾粏淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('da:passingStationCollection:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(daPassingStationCollectionService.selectDaPassingStationCollectionById(id));
+    }
+
+    /**
+     * 鏂板浜у搧杩囩珯閲囬泦
+     */
+    @PreAuthorize("@ss.hasPermi('da:passingStationCollection:add')")
+    @Log(title = "浜у搧杩囩珯閲囬泦", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody DaPassingStationCollection daPassingStationCollection)
+    {
+        daPassingStationCollection.setCreateBy(getUsername());
+        daPassingStationCollection.setCreateTime(DateUtils.getNowDate());
+        return toAjax(daPassingStationCollectionService.insertDaPassingStationCollection(daPassingStationCollection));
+    }
+
+    /**
+     * 淇敼浜у搧杩囩珯閲囬泦
+     */
+    @PreAuthorize("@ss.hasPermi('da:passingStationCollection:edit')")
+    @Log(title = "浜у搧杩囩珯閲囬泦", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody DaPassingStationCollection daPassingStationCollection)
+    {
+        daPassingStationCollection.setUpdateBy(getUsername());
+        daPassingStationCollection.setUpdateTime(DateUtils.getNowDate());
+        return toAjax(daPassingStationCollectionService.updateDaPassingStationCollection(daPassingStationCollection));
+    }
+
+    /**
+     * 鍒犻櫎浜у搧杩囩珯閲囬泦
+     */
+    @PreAuthorize("@ss.hasPermi('da:passingStationCollection:remove')")
+    @Log(title = "浜у搧杩囩珯閲囬泦", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(daPassingStationCollectionService.deleteDaPassingStationCollectionByIds(ids));
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/domain/DaPassingStationCollection.java b/jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/domain/DaPassingStationCollection.java
new file mode 100644
index 0000000..f6ce656
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/domain/DaPassingStationCollection.java
@@ -0,0 +1,302 @@
+package com.jcdm.main.da.passingStationCollection.domain;
+
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.core.domain.BaseEntity;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+import java.util.Date;
+
+/**
+ * 浜у搧杩囩珯閲囬泦瀵硅薄 da_passing_station_collection
+ * 
+ * @author yyt
+ * @date 2023-12-12
+ */
+public class DaPassingStationCollection extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 涓婚敭id */
+    private Long id;
+
+    /** 宸ュ崟缂栧彿 */
+    @Excel(name = "宸ュ崟缂栧彿")
+    private String workOrderNo;
+
+    /** 鎬绘垚搴忓垪鍙� */
+    @Excel(name = "鎬绘垚搴忓垪鍙�")
+    private String sfcCode;
+
+    /** 浜у搧缂栧彿 */
+    @Excel(name = "浜у搧缂栧彿")
+    private String productCode;
+
+    /** 浜х嚎缂栧彿 */
+    @Excel(name = "浜х嚎缂栧彿")
+    private String productionLine;
+
+    /** 宸ヤ綅缂栧彿 */
+    @Excel(name = "宸ヤ綅缂栧彿")
+    private String locationCode;
+
+    /** 璁惧缂栧彿 */
+    @Excel(name = "璁惧缂栧彿")
+    private String equipmentNo;
+
+    /** 鍏ョ珯鏃堕棿 */
+//    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "鍏ョ珯鏃堕棿")
+    private Date inboundTime;
+
+    /** 鍑虹珯鏃堕棿 */
+//    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "鍑虹珯鏃堕棿")
+    private Date outboundTime;
+
+    /** 鍏ョ珯鏄惁鍚堟牸 */
+    @Excel(name = "鍏ョ珯鏄惁鍚堟牸")
+    private String inRsSign;
+
+    /** 鍏ョ珯NG鍘熷洜 */
+    @Excel(name = "鍏ョ珯NG鍘熷洜")
+    private String inMsgSign;
+
+    /** 鍑虹珯鏄惁鍚堟牸 */
+    @Excel(name = "鍑虹珯鏄惁鍚堟牸")
+    private String outRsSign;
+
+    /** 鍑虹珯NG鍘熷洜 */
+    @Excel(name = "鍑虹珯NG鍘熷洜")
+    private String outMsgSign;
+
+    /** 閲囬泦鏃堕棿 */
+//    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "閲囬泦鏃堕棿")
+    private Date collectionTime;
+
+    /** 棰勭暀瀛楁1 */
+    private String spareField1;
+
+    /** 棰勭暀瀛楁2 */
+    private String spareField2;
+
+    /** 鍒涘缓鐢ㄦ埛 */
+    private String createUser;
+
+    /** 鏇存敼鐢ㄦ埛 */
+    private String updateUser;
+
+    /** 鑺傛媿鏃堕棿 */
+    @Excel(name = "鑺傛媿鏃堕棿")
+    private String beatTime;
+
+    private Long[] ids;
+
+    public Long[] getIds() {
+        return ids;
+    }
+
+    public void setIds(Long[] ids) {
+        this.ids = ids;
+    }
+
+    public void setId(Long id)
+    {
+        this.id = id;
+    }
+
+    public Long getId() 
+    {
+        return id;
+    }
+    public void setWorkOrderNo(String workOrderNo) 
+    {
+        this.workOrderNo = workOrderNo;
+    }
+
+    public String getWorkOrderNo() 
+    {
+        return workOrderNo;
+    }
+    public void setSfcCode(String sfcCode) 
+    {
+        this.sfcCode = sfcCode;
+    }
+
+    public String getSfcCode() 
+    {
+        return sfcCode;
+    }
+    public void setProductCode(String productCode) 
+    {
+        this.productCode = productCode;
+    }
+
+    public String getProductCode() 
+    {
+        return productCode;
+    }
+    public void setProductionLine(String productionLine) 
+    {
+        this.productionLine = productionLine;
+    }
+
+    public String getProductionLine() 
+    {
+        return productionLine;
+    }
+    public void setLocationCode(String locationCode) 
+    {
+        this.locationCode = locationCode;
+    }
+
+    public String getLocationCode() 
+    {
+        return locationCode;
+    }
+    public void setEquipmentNo(String equipmentNo) 
+    {
+        this.equipmentNo = equipmentNo;
+    }
+
+    public String getEquipmentNo() 
+    {
+        return equipmentNo;
+    }
+    public void setInboundTime(Date inboundTime) 
+    {
+        this.inboundTime = inboundTime;
+    }
+
+    public Date getInboundTime() 
+    {
+        return inboundTime;
+    }
+    public void setOutboundTime(Date outboundTime) 
+    {
+        this.outboundTime = outboundTime;
+    }
+
+    public Date getOutboundTime() 
+    {
+        return outboundTime;
+    }
+    public void setInRsSign(String inRsSign) 
+    {
+        this.inRsSign = inRsSign;
+    }
+
+    public String getInRsSign() 
+    {
+        return inRsSign;
+    }
+    public void setInMsgSign(String inMsgSign) 
+    {
+        this.inMsgSign = inMsgSign;
+    }
+
+    public String getInMsgSign() 
+    {
+        return inMsgSign;
+    }
+    public void setOutRsSign(String outRsSign) 
+    {
+        this.outRsSign = outRsSign;
+    }
+
+    public String getOutRsSign() 
+    {
+        return outRsSign;
+    }
+    public void setOutMsgSign(String outMsgSign) 
+    {
+        this.outMsgSign = outMsgSign;
+    }
+
+    public String getOutMsgSign() 
+    {
+        return outMsgSign;
+    }
+    public void setCollectionTime(Date collectionTime) 
+    {
+        this.collectionTime = collectionTime;
+    }
+
+    public Date getCollectionTime() 
+    {
+        return collectionTime;
+    }
+    public void setSpareField1(String spareField1) 
+    {
+        this.spareField1 = spareField1;
+    }
+
+    public String getSpareField1() 
+    {
+        return spareField1;
+    }
+    public void setSpareField2(String spareField2) 
+    {
+        this.spareField2 = spareField2;
+    }
+
+    public String getSpareField2() 
+    {
+        return spareField2;
+    }
+    public void setCreateUser(String createUser) 
+    {
+        this.createUser = createUser;
+    }
+
+    public String getCreateUser() 
+    {
+        return createUser;
+    }
+    public void setUpdateUser(String updateUser) 
+    {
+        this.updateUser = updateUser;
+    }
+
+    public String getUpdateUser() 
+    {
+        return updateUser;
+    }
+    public void setBeatTime(String beatTime) 
+    {
+        this.beatTime = beatTime;
+    }
+
+    public String getBeatTime() 
+    {
+        return beatTime;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("workOrderNo", getWorkOrderNo())
+            .append("sfcCode", getSfcCode())
+            .append("productCode", getProductCode())
+            .append("productionLine", getProductionLine())
+            .append("locationCode", getLocationCode())
+            .append("equipmentNo", getEquipmentNo())
+            .append("inboundTime", getInboundTime())
+            .append("outboundTime", getOutboundTime())
+            .append("inRsSign", getInRsSign())
+            .append("inMsgSign", getInMsgSign())
+            .append("outRsSign", getOutRsSign())
+            .append("outMsgSign", getOutMsgSign())
+            .append("collectionTime", getCollectionTime())
+            .append("spareField1", getSpareField1())
+            .append("spareField2", getSpareField2())
+            .append("createUser", getCreateUser())
+            .append("createTime", getCreateTime())
+            .append("updateUser", getUpdateUser())
+            .append("updateTime", getUpdateTime())
+            .append("beatTime", getBeatTime())
+            .toString();
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/mapper/DaPassingStationCollectionMapper.java b/jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/mapper/DaPassingStationCollectionMapper.java
new file mode 100644
index 0000000..e7ef05e
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/mapper/DaPassingStationCollectionMapper.java
@@ -0,0 +1,62 @@
+package com.jcdm.main.da.passingStationCollection.mapper;
+
+import com.jcdm.main.da.passingStationCollection.domain.DaPassingStationCollection;
+
+import java.util.List;
+
+/**
+ * 浜у搧杩囩珯閲囬泦Mapper鎺ュ彛
+ * 
+ * @author yyt
+ * @date 2023-12-12
+ */
+public interface DaPassingStationCollectionMapper 
+{
+    /**
+     * 鏌ヨ浜у搧杩囩珯閲囬泦
+     * 
+     * @param id 浜у搧杩囩珯閲囬泦涓婚敭
+     * @return 浜у搧杩囩珯閲囬泦
+     */
+    public DaPassingStationCollection selectDaPassingStationCollectionById(Long id);
+
+    /**
+     * 鏌ヨ浜у搧杩囩珯閲囬泦鍒楄〃
+     * 
+     * @param daPassingStationCollection 浜у搧杩囩珯閲囬泦
+     * @return 浜у搧杩囩珯閲囬泦闆嗗悎
+     */
+    public List<DaPassingStationCollection> selectDaPassingStationCollectionList(DaPassingStationCollection daPassingStationCollection);
+
+    /**
+     * 鏂板浜у搧杩囩珯閲囬泦
+     * 
+     * @param daPassingStationCollection 浜у搧杩囩珯閲囬泦
+     * @return 缁撴灉
+     */
+    public int insertDaPassingStationCollection(DaPassingStationCollection daPassingStationCollection);
+
+    /**
+     * 淇敼浜у搧杩囩珯閲囬泦
+     * 
+     * @param daPassingStationCollection 浜у搧杩囩珯閲囬泦
+     * @return 缁撴灉
+     */
+    public int updateDaPassingStationCollection(DaPassingStationCollection daPassingStationCollection);
+
+    /**
+     * 鍒犻櫎浜у搧杩囩珯閲囬泦
+     * 
+     * @param id 浜у搧杩囩珯閲囬泦涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteDaPassingStationCollectionById(Long id);
+
+    /**
+     * 鎵归噺鍒犻櫎浜у搧杩囩珯閲囬泦
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteDaPassingStationCollectionByIds(Long[] ids);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/service/IDaPassingStationCollectionService.java b/jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/service/IDaPassingStationCollectionService.java
new file mode 100644
index 0000000..f3cd0ca
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/service/IDaPassingStationCollectionService.java
@@ -0,0 +1,72 @@
+package com.jcdm.main.da.passingStationCollection.service;
+
+import com.jcdm.main.da.passingStationCollection.domain.DaPassingStationCollection;
+
+import java.util.List;
+
+/**
+ * 浜у搧杩囩珯閲囬泦Service鎺ュ彛
+ * 
+ * @author yyt
+ * @date 2023-12-12
+ */
+public interface IDaPassingStationCollectionService 
+{
+    /**
+     * 鏌ヨ浜у搧杩囩珯閲囬泦
+     * 
+     * @param id 浜у搧杩囩珯閲囬泦涓婚敭
+     * @return 浜у搧杩囩珯閲囬泦
+     */
+    public DaPassingStationCollection selectDaPassingStationCollectionById(Long id);
+
+    /**
+     * 鏌ヨ浜у搧杩囩珯閲囬泦鍒楄〃
+     * 
+     * @param daPassingStationCollection 浜у搧杩囩珯閲囬泦
+     * @return 浜у搧杩囩珯閲囬泦闆嗗悎
+     */
+    public List<DaPassingStationCollection> selectDaPassingStationCollectionList(DaPassingStationCollection daPassingStationCollection);
+
+
+//    /**
+//     * 鑾峰彇棣栭〉鍗曟棩绱閲忎骇鏁版嵁
+//     * @param fieldName bs
+//     * @return list
+//     */
+//    public Integer getProduceNumToday(String fieldName);
+
+    /**
+     * 鏂板浜у搧杩囩珯閲囬泦
+     * 
+     * @param daPassingStationCollection 浜у搧杩囩珯閲囬泦
+     * @return 缁撴灉
+     */
+    public int insertDaPassingStationCollection(DaPassingStationCollection daPassingStationCollection);
+
+    /**
+     * 淇敼浜у搧杩囩珯閲囬泦
+     * 
+     * @param daPassingStationCollection 浜у搧杩囩珯閲囬泦
+     * @return 缁撴灉
+     */
+    public int updateDaPassingStationCollection(DaPassingStationCollection daPassingStationCollection);
+
+    /**
+     * 鎵归噺鍒犻櫎浜у搧杩囩珯閲囬泦
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑浜у搧杩囩珯閲囬泦涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteDaPassingStationCollectionByIds(Long[] ids);
+
+    /**
+     * 鍒犻櫎浜у搧杩囩珯閲囬泦淇℃伅
+     * 
+     * @param id 浜у搧杩囩珯閲囬泦涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteDaPassingStationCollectionById(Long id);
+
+    void insertRepairRecordByIds(DaPassingStationCollection daPassingStationCollection);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/service/impl/DaPassingStationCollectionServiceImpl.java b/jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/service/impl/DaPassingStationCollectionServiceImpl.java
new file mode 100644
index 0000000..a45c08e
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/service/impl/DaPassingStationCollectionServiceImpl.java
@@ -0,0 +1,147 @@
+package com.jcdm.main.da.passingStationCollection.service.impl;
+
+import com.jcdm.common.utils.DateUtils;
+//import com.jcdm.main.bs.orderScheduling.domain.BsOrderScheduling;
+//import com.jcdm.main.bs.orderScheduling.mapper.BsOrderSchedulingMapper;
+//import com.jcdm.main.bs.orderScheduling.service.IBsOrderSchedulingService;
+import com.jcdm.main.da.passingStationCollection.domain.DaPassingStationCollection;
+import com.jcdm.main.da.passingStationCollection.mapper.DaPassingStationCollectionMapper;
+import com.jcdm.main.da.passingStationCollection.service.IDaPassingStationCollectionService;
+import com.jcdm.main.rm.repairRecord.domain.RmRepairRecord;
+import com.jcdm.main.rm.repairRecord.mapper.RmRepairRecordMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.List;
+
+/**
+ * 浜у搧杩囩珯閲囬泦Service涓氬姟灞傚鐞�
+ * 
+ * @author yyt
+ * @date 2023-12-12
+ */
+@Service
+public class DaPassingStationCollectionServiceImpl implements IDaPassingStationCollectionService
+{
+    @Autowired
+    private DaPassingStationCollectionMapper daPassingStationCollectionMapper;
+
+    @Autowired
+    private RmRepairRecordMapper rmRepairRecordMapper;
+
+//    @Autowired
+//    private BsOrderSchedulingMapper bsOrderSchedulingMapper;
+//
+//    @Autowired
+//    private IBsOrderSchedulingService bsOrderSchedulingService;
+
+    /**
+     * 鏌ヨ浜у搧杩囩珯閲囬泦
+     * 
+     * @param id 浜у搧杩囩珯閲囬泦涓婚敭
+     * @return 浜у搧杩囩珯閲囬泦
+     */
+    @Override
+    public DaPassingStationCollection selectDaPassingStationCollectionById(Long id)
+    {
+        return daPassingStationCollectionMapper.selectDaPassingStationCollectionById(id);
+    }
+
+    /**
+     * 鏌ヨ浜у搧杩囩珯閲囬泦鍒楄〃
+     * 
+     * @param daPassingStationCollection 浜у搧杩囩珯閲囬泦
+     * @return 浜у搧杩囩珯閲囬泦
+     */
+    @Override
+    public List<DaPassingStationCollection> selectDaPassingStationCollectionList(DaPassingStationCollection daPassingStationCollection)
+    {
+        return daPassingStationCollectionMapper.selectDaPassingStationCollectionList(daPassingStationCollection);
+    }
+
+//    /**
+//     * 鑾峰彇棣栭〉鍗曟棩绱閲忎骇鏁版嵁
+//     * @param fieldName bs
+//     * @return list
+//     */
+//    @Override
+//    public Integer getProduceNumToday(String fieldName) {
+//
+//        BsOrderScheduling bsOrderScheduling = new BsOrderScheduling();
+//        bsOrderScheduling.setQueryField(fieldName);
+//        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+//        LocalDateTime startTime = LocalDate.now().atStartOfDay();
+//        LocalDateTime endTime = LocalDate.now().plusDays(1).atStartOfDay();
+//        String s1 = startTime.format(formatter);
+//        String s2 = endTime.format(formatter);
+//        bsOrderScheduling.setStartTime(s1);
+//        bsOrderScheduling.setEndTime(s2);
+//        return bsOrderSchedulingMapper.getProduceNumToday(bsOrderScheduling);
+//    }
+
+    /**
+     * 鏂板浜у搧杩囩珯閲囬泦
+     * 
+     * @param daPassingStationCollection 浜у搧杩囩珯閲囬泦
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertDaPassingStationCollection(DaPassingStationCollection daPassingStationCollection)
+    {
+        daPassingStationCollection.setCreateTime(DateUtils.getNowDate());
+        return daPassingStationCollectionMapper.insertDaPassingStationCollection(daPassingStationCollection);
+    }
+
+    /**
+     * 淇敼浜у搧杩囩珯閲囬泦
+     * 
+     * @param daPassingStationCollection 浜у搧杩囩珯閲囬泦
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateDaPassingStationCollection(DaPassingStationCollection daPassingStationCollection)
+    {
+        daPassingStationCollection.setUpdateTime(DateUtils.getNowDate());
+        return daPassingStationCollectionMapper.updateDaPassingStationCollection(daPassingStationCollection);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎浜у搧杩囩珯閲囬泦
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑浜у搧杩囩珯閲囬泦涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteDaPassingStationCollectionByIds(Long[] ids)
+    {
+        return daPassingStationCollectionMapper.deleteDaPassingStationCollectionByIds(ids);
+    }
+
+    /**
+     * 鍒犻櫎浜у搧杩囩珯閲囬泦淇℃伅
+     * 
+     * @param id 浜у搧杩囩珯閲囬泦涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteDaPassingStationCollectionById(Long id)
+    {
+        return daPassingStationCollectionMapper.deleteDaPassingStationCollectionById(id);
+    }
+
+    @Override
+    public void insertRepairRecordByIds(DaPassingStationCollection daPassingStationCollection) {
+        Long[] conditions = daPassingStationCollection.getIds();
+        for (int i = 0; i < conditions.length; i++) {
+            DaPassingStationCollection result = daPassingStationCollectionMapper.selectDaPassingStationCollectionById(conditions[i]);
+            RmRepairRecord rmRepairRecord = new RmRepairRecord();
+            rmRepairRecord.setBoxCode(result.getSfcCode());
+            rmRepairRecord.setProcessesCode(result.getLocationCode());
+            rmRepairRecord.setOriginalResult(result.getOutRsSign());
+            rmRepairRecordMapper.insertRmRepairRecord(rmRepairRecord);
+        }
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/em/equipmentAlarm/controller/EmEquipmentAlarmController.java b/jcdm-main/src/main/java/com/jcdm/main/em/equipmentAlarm/controller/EmEquipmentAlarmController.java
new file mode 100644
index 0000000..34259af
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/em/equipmentAlarm/controller/EmEquipmentAlarmController.java
@@ -0,0 +1,105 @@
+package com.jcdm.main.em.equipmentAlarm.controller;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.jcdm.main.em.equipmentAlarm.domain.EmEquipmentAlarm;
+import com.jcdm.main.em.equipmentAlarm.service.IEmEquipmentAlarmService;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.common.utils.poi.ExcelUtil;
+import com.jcdm.common.core.page.TableDataInfo;
+
+/**
+ * 璁惧鎶ヨController
+ * 
+ * @author ruimin
+ * @date 2023-12-15
+ */
+@RestController
+@RequestMapping("/em/equipmentAlarm")
+public class EmEquipmentAlarmController extends BaseController
+{
+    @Autowired
+    private IEmEquipmentAlarmService emEquipmentAlarmService;
+
+    /**
+     * 鏌ヨ璁惧鎶ヨ鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('em:equipmentAlarm:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(EmEquipmentAlarm emEquipmentAlarm)
+    {
+        startPage();
+        List<EmEquipmentAlarm> list = emEquipmentAlarmService.selectEmEquipmentAlarmList(emEquipmentAlarm);
+        return getDataTable(list);
+    }
+
+    /**
+     * 瀵煎嚭璁惧鎶ヨ鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('em:equipmentAlarm:export')")
+    @Log(title = "璁惧鎶ヨ", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, EmEquipmentAlarm emEquipmentAlarm)
+    {
+        List<EmEquipmentAlarm> list = emEquipmentAlarmService.selectEmEquipmentAlarmList(emEquipmentAlarm);
+        ExcelUtil<EmEquipmentAlarm> util = new ExcelUtil<EmEquipmentAlarm>(EmEquipmentAlarm.class);
+        util.exportExcel(response, list, "璁惧鎶ヨ鏁版嵁");
+    }
+
+    /**
+     * 鑾峰彇璁惧鎶ヨ璇︾粏淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('em:equipmentAlarm:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(emEquipmentAlarmService.selectEmEquipmentAlarmById(id));
+    }
+
+    /**
+     * 鏂板璁惧鎶ヨ
+     */
+    @PreAuthorize("@ss.hasPermi('em:equipmentAlarm:add')")
+    @Log(title = "璁惧鎶ヨ", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody EmEquipmentAlarm emEquipmentAlarm)
+    {
+        return toAjax(emEquipmentAlarmService.insertEmEquipmentAlarm(emEquipmentAlarm));
+    }
+
+    /**
+     * 淇敼璁惧鎶ヨ
+     */
+    @PreAuthorize("@ss.hasPermi('em:equipmentAlarm:edit')")
+    @Log(title = "璁惧鎶ヨ", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody EmEquipmentAlarm emEquipmentAlarm)
+    {
+        return toAjax(emEquipmentAlarmService.updateEmEquipmentAlarm(emEquipmentAlarm));
+    }
+
+    /**
+     * 鍒犻櫎璁惧鎶ヨ
+     */
+    @PreAuthorize("@ss.hasPermi('em:equipmentAlarm:remove')")
+    @Log(title = "璁惧鎶ヨ", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(emEquipmentAlarmService.deleteEmEquipmentAlarmByIds(ids));
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/em/equipmentAlarm/domain/EmEquipmentAlarm.java b/jcdm-main/src/main/java/com/jcdm/main/em/equipmentAlarm/domain/EmEquipmentAlarm.java
new file mode 100644
index 0000000..2717dcc
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/em/equipmentAlarm/domain/EmEquipmentAlarm.java
@@ -0,0 +1,257 @@
+package com.jcdm.main.em.equipmentAlarm.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.core.domain.BaseEntity;
+
+/**
+ * 璁惧鎶ヨ瀵硅薄 em_equipment_alarm
+ * 
+ * @author ruimin
+ * @date 2023-12-15
+ */
+public class EmEquipmentAlarm extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** ID */
+    private Long id;
+
+    /** 璁惧缂栧彿 */
+    @Excel(name = "璁惧缂栧彿")
+    private String equipmentCode;
+
+    /** 璁惧鍚嶇О */
+    @Excel(name = "璁惧鍚嶇О")
+    private String equipmentName;
+
+    /** 璁惧绫诲瀷 */
+    @Excel(name = "璁惧绫诲瀷")
+    private String equipmentType;
+
+    /** 杞﹂棿缂栧彿 */
+    @Excel(name = "杞﹂棿缂栧彿")
+    private String workshopCode;
+
+    /** 浜х嚎缂栧彿 */
+    @Excel(name = "浜х嚎缂栧彿")
+    private String lineCode;
+
+    /** 宸ュ簭缂栧彿 */
+    @Excel(name = "宸ュ簭缂栧彿")
+    private String processesCode;
+
+    /** 鏁呴殰浠g爜 */
+    @Excel(name = "鏁呴殰浠g爜")
+    private String errorNo;
+
+    /** 鏁呴殰鎻忚堪 */
+    @Excel(name = "鏁呴殰鎻忚堪")
+    private String errorDesc;
+
+    /** 鎶ヨ鏃堕棿 */
+    @Excel(name = "鎶ヨ鏃堕棿")
+    private String alarmTime;
+
+    /** 鏄惁鎭㈠(0鍚�1鏄�) */
+    @Excel(name = "鏄惁鎭㈠(0鍚�1鏄�)")
+    private String whetherRecovery;
+
+    /** 鎭㈠鏃堕棿 */
+    @Excel(name = "鎭㈠鏃堕棿")
+    private String recoveryTime;
+
+    /** 棰勭暀瀛楁1 */
+    private String spareField1;
+
+    /** 棰勭暀瀛楁2 */
+    private String spareField2;
+
+    /** 棰勭暀瀛楁3 */
+    private String spareField3;
+
+    /** 棰勭暀瀛楁4 */
+    private String spareField4;
+
+    /** 澶囨敞 */
+    @Excel(name = "澶囨敞")
+    private String remarks;
+
+    public void setId(Long id) 
+    {
+        this.id = id;
+    }
+
+    public Long getId() 
+    {
+        return id;
+    }
+    public void setEquipmentCode(String equipmentCode) 
+    {
+        this.equipmentCode = equipmentCode;
+    }
+
+    public String getEquipmentCode() 
+    {
+        return equipmentCode;
+    }
+    public void setEquipmentName(String equipmentName) 
+    {
+        this.equipmentName = equipmentName;
+    }
+
+    public String getEquipmentName() 
+    {
+        return equipmentName;
+    }
+    public void setEquipmentType(String equipmentType) 
+    {
+        this.equipmentType = equipmentType;
+    }
+
+    public String getEquipmentType() 
+    {
+        return equipmentType;
+    }
+    public void setWorkshopCode(String workshopCode) 
+    {
+        this.workshopCode = workshopCode;
+    }
+
+    public String getWorkshopCode() 
+    {
+        return workshopCode;
+    }
+    public void setLineCode(String lineCode) 
+    {
+        this.lineCode = lineCode;
+    }
+
+    public String getLineCode() 
+    {
+        return lineCode;
+    }
+    public void setProcessesCode(String processesCode) 
+    {
+        this.processesCode = processesCode;
+    }
+
+    public String getProcessesCode() 
+    {
+        return processesCode;
+    }
+    public void setErrorNo(String errorNo) 
+    {
+        this.errorNo = errorNo;
+    }
+
+    public String getErrorNo() 
+    {
+        return errorNo;
+    }
+    public void setErrorDesc(String errorDesc) 
+    {
+        this.errorDesc = errorDesc;
+    }
+
+    public String getErrorDesc() 
+    {
+        return errorDesc;
+    }
+    public void setAlarmTime(String alarmTime) 
+    {
+        this.alarmTime = alarmTime;
+    }
+
+    public String getAlarmTime() 
+    {
+        return alarmTime;
+    }
+    public void setWhetherRecovery(String whetherRecovery) 
+    {
+        this.whetherRecovery = whetherRecovery;
+    }
+
+    public String getWhetherRecovery() 
+    {
+        return whetherRecovery;
+    }
+    public void setRecoveryTime(String recoveryTime) 
+    {
+        this.recoveryTime = recoveryTime;
+    }
+
+    public String getRecoveryTime() 
+    {
+        return recoveryTime;
+    }
+    public void setSpareField1(String spareField1) 
+    {
+        this.spareField1 = spareField1;
+    }
+
+    public String getSpareField1() 
+    {
+        return spareField1;
+    }
+    public void setSpareField2(String spareField2) 
+    {
+        this.spareField2 = spareField2;
+    }
+
+    public String getSpareField2() 
+    {
+        return spareField2;
+    }
+    public void setSpareField3(String spareField3) 
+    {
+        this.spareField3 = spareField3;
+    }
+
+    public String getSpareField3() 
+    {
+        return spareField3;
+    }
+    public void setSpareField4(String spareField4) 
+    {
+        this.spareField4 = spareField4;
+    }
+
+    public String getSpareField4() 
+    {
+        return spareField4;
+    }
+    public void setRemarks(String remarks) 
+    {
+        this.remarks = remarks;
+    }
+
+    public String getRemarks() 
+    {
+        return remarks;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("equipmentCode", getEquipmentCode())
+            .append("equipmentName", getEquipmentName())
+            .append("equipmentType", getEquipmentType())
+            .append("workshopCode", getWorkshopCode())
+            .append("lineCode", getLineCode())
+            .append("processesCode", getProcessesCode())
+            .append("errorNo", getErrorNo())
+            .append("errorDesc", getErrorDesc())
+            .append("alarmTime", getAlarmTime())
+            .append("whetherRecovery", getWhetherRecovery())
+            .append("recoveryTime", getRecoveryTime())
+            .append("spareField1", getSpareField1())
+            .append("spareField2", getSpareField2())
+            .append("spareField3", getSpareField3())
+            .append("spareField4", getSpareField4())
+            .append("remarks", getRemarks())
+            .toString();
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/em/equipmentAlarm/mapper/EmEquipmentAlarmMapper.java b/jcdm-main/src/main/java/com/jcdm/main/em/equipmentAlarm/mapper/EmEquipmentAlarmMapper.java
new file mode 100644
index 0000000..56392bf
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/em/equipmentAlarm/mapper/EmEquipmentAlarmMapper.java
@@ -0,0 +1,62 @@
+package com.jcdm.main.em.equipmentAlarm.mapper;
+
+import com.jcdm.main.em.equipmentAlarm.domain.EmEquipmentAlarm;
+
+import java.util.List;
+
+/**
+ * 璁惧鎶ヨMapper鎺ュ彛
+ * 
+ * @author ruimin
+ * @date 2023-12-15
+ */
+public interface EmEquipmentAlarmMapper 
+{
+    /**
+     * 鏌ヨ璁惧鎶ヨ
+     * 
+     * @param id 璁惧鎶ヨ涓婚敭
+     * @return 璁惧鎶ヨ
+     */
+    public EmEquipmentAlarm selectEmEquipmentAlarmById(Long id);
+
+    /**
+     * 鏌ヨ璁惧鎶ヨ鍒楄〃
+     * 
+     * @param emEquipmentAlarm 璁惧鎶ヨ
+     * @return 璁惧鎶ヨ闆嗗悎
+     */
+    public List<EmEquipmentAlarm> selectEmEquipmentAlarmList(EmEquipmentAlarm emEquipmentAlarm);
+
+    /**
+     * 鏂板璁惧鎶ヨ
+     * 
+     * @param emEquipmentAlarm 璁惧鎶ヨ
+     * @return 缁撴灉
+     */
+    public int insertEmEquipmentAlarm(EmEquipmentAlarm emEquipmentAlarm);
+
+    /**
+     * 淇敼璁惧鎶ヨ
+     * 
+     * @param emEquipmentAlarm 璁惧鎶ヨ
+     * @return 缁撴灉
+     */
+    public int updateEmEquipmentAlarm(EmEquipmentAlarm emEquipmentAlarm);
+
+    /**
+     * 鍒犻櫎璁惧鎶ヨ
+     * 
+     * @param id 璁惧鎶ヨ涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteEmEquipmentAlarmById(Long id);
+
+    /**
+     * 鎵归噺鍒犻櫎璁惧鎶ヨ
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteEmEquipmentAlarmByIds(Long[] ids);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/em/equipmentAlarm/service/IEmEquipmentAlarmService.java b/jcdm-main/src/main/java/com/jcdm/main/em/equipmentAlarm/service/IEmEquipmentAlarmService.java
new file mode 100644
index 0000000..817395e
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/em/equipmentAlarm/service/IEmEquipmentAlarmService.java
@@ -0,0 +1,62 @@
+package com.jcdm.main.em.equipmentAlarm.service;
+
+import com.jcdm.main.em.equipmentAlarm.domain.EmEquipmentAlarm;
+
+import java.util.List;
+
+/**
+ * 璁惧鎶ヨService鎺ュ彛
+ * 
+ * @author ruimin
+ * @date 2023-12-15
+ */
+public interface IEmEquipmentAlarmService 
+{
+    /**
+     * 鏌ヨ璁惧鎶ヨ
+     * 
+     * @param id 璁惧鎶ヨ涓婚敭
+     * @return 璁惧鎶ヨ
+     */
+    public EmEquipmentAlarm selectEmEquipmentAlarmById(Long id);
+
+    /**
+     * 鏌ヨ璁惧鎶ヨ鍒楄〃
+     * 
+     * @param emEquipmentAlarm 璁惧鎶ヨ
+     * @return 璁惧鎶ヨ闆嗗悎
+     */
+    public List<EmEquipmentAlarm> selectEmEquipmentAlarmList(EmEquipmentAlarm emEquipmentAlarm);
+
+    /**
+     * 鏂板璁惧鎶ヨ
+     * 
+     * @param emEquipmentAlarm 璁惧鎶ヨ
+     * @return 缁撴灉
+     */
+    public int insertEmEquipmentAlarm(EmEquipmentAlarm emEquipmentAlarm);
+
+    /**
+     * 淇敼璁惧鎶ヨ
+     * 
+     * @param emEquipmentAlarm 璁惧鎶ヨ
+     * @return 缁撴灉
+     */
+    public int updateEmEquipmentAlarm(EmEquipmentAlarm emEquipmentAlarm);
+
+    /**
+     * 鎵归噺鍒犻櫎璁惧鎶ヨ
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑璁惧鎶ヨ涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteEmEquipmentAlarmByIds(Long[] ids);
+
+    /**
+     * 鍒犻櫎璁惧鎶ヨ淇℃伅
+     * 
+     * @param id 璁惧鎶ヨ涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteEmEquipmentAlarmById(Long id);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/em/equipmentAlarm/service/impl/EmEquipmentAlarmServiceImpl.java b/jcdm-main/src/main/java/com/jcdm/main/em/equipmentAlarm/service/impl/EmEquipmentAlarmServiceImpl.java
new file mode 100644
index 0000000..ccfd5fc
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/em/equipmentAlarm/service/impl/EmEquipmentAlarmServiceImpl.java
@@ -0,0 +1,94 @@
+package com.jcdm.main.em.equipmentAlarm.service.impl;
+
+import java.util.List;
+
+import com.jcdm.main.em.equipmentAlarm.domain.EmEquipmentAlarm;
+import com.jcdm.main.em.equipmentAlarm.mapper.EmEquipmentAlarmMapper;
+import com.jcdm.main.em.equipmentAlarm.service.IEmEquipmentAlarmService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * 璁惧鎶ヨService涓氬姟灞傚鐞�
+ * 
+ * @author ruimin
+ * @date 2023-12-15
+ */
+@Service
+public class EmEquipmentAlarmServiceImpl implements IEmEquipmentAlarmService
+{
+    @Autowired
+    private EmEquipmentAlarmMapper emEquipmentAlarmMapper;
+
+    /**
+     * 鏌ヨ璁惧鎶ヨ
+     * 
+     * @param id 璁惧鎶ヨ涓婚敭
+     * @return 璁惧鎶ヨ
+     */
+    @Override
+    public EmEquipmentAlarm selectEmEquipmentAlarmById(Long id)
+    {
+        return emEquipmentAlarmMapper.selectEmEquipmentAlarmById(id);
+    }
+
+    /**
+     * 鏌ヨ璁惧鎶ヨ鍒楄〃
+     * 
+     * @param emEquipmentAlarm 璁惧鎶ヨ
+     * @return 璁惧鎶ヨ
+     */
+    @Override
+    public List<EmEquipmentAlarm> selectEmEquipmentAlarmList(EmEquipmentAlarm emEquipmentAlarm)
+    {
+        return emEquipmentAlarmMapper.selectEmEquipmentAlarmList(emEquipmentAlarm);
+    }
+
+    /**
+     * 鏂板璁惧鎶ヨ
+     * 
+     * @param emEquipmentAlarm 璁惧鎶ヨ
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertEmEquipmentAlarm(EmEquipmentAlarm emEquipmentAlarm)
+    {
+        return emEquipmentAlarmMapper.insertEmEquipmentAlarm(emEquipmentAlarm);
+    }
+
+    /**
+     * 淇敼璁惧鎶ヨ
+     * 
+     * @param emEquipmentAlarm 璁惧鎶ヨ
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateEmEquipmentAlarm(EmEquipmentAlarm emEquipmentAlarm)
+    {
+        return emEquipmentAlarmMapper.updateEmEquipmentAlarm(emEquipmentAlarm);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎璁惧鎶ヨ
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑璁惧鎶ヨ涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteEmEquipmentAlarmByIds(Long[] ids)
+    {
+        return emEquipmentAlarmMapper.deleteEmEquipmentAlarmByIds(ids);
+    }
+
+    /**
+     * 鍒犻櫎璁惧鎶ヨ淇℃伅
+     * 
+     * @param id 璁惧鎶ヨ涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteEmEquipmentAlarmById(Long id)
+    {
+        return emEquipmentAlarmMapper.deleteEmEquipmentAlarmById(id);
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/em/equipmentArchives/controller/EmEquipmentArchivesController.java b/jcdm-main/src/main/java/com/jcdm/main/em/equipmentArchives/controller/EmEquipmentArchivesController.java
new file mode 100644
index 0000000..8609f5c
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/em/equipmentArchives/controller/EmEquipmentArchivesController.java
@@ -0,0 +1,104 @@
+package com.jcdm.main.em.equipmentArchives.controller;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.main.em.equipmentArchives.domain.EmEquipmentArchives;
+import com.jcdm.main.em.equipmentArchives.service.IEmEquipmentArchivesService;
+import com.jcdm.common.utils.poi.ExcelUtil;
+import com.jcdm.common.core.page.TableDataInfo;
+
+/**
+ * 璁惧妗fController
+ * 
+ * @author Yi
+ * @date 2023-12-26
+ */
+@RestController
+@RequestMapping("/em/equipmentArchives")
+public class EmEquipmentArchivesController extends BaseController
+{
+    @Autowired
+    private IEmEquipmentArchivesService emEquipmentArchivesService;
+
+    /**
+     * 鏌ヨ璁惧妗f鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('em:equipmentArchives:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(EmEquipmentArchives emEquipmentArchives)
+    {
+        startPage();
+        List<EmEquipmentArchives> list = emEquipmentArchivesService.selectEmEquipmentArchivesList(emEquipmentArchives);
+        return getDataTable(list);
+    }
+
+    /**
+     * 瀵煎嚭璁惧妗f鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('em:equipmentArchives:export')")
+    @Log(title = "璁惧妗f", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, EmEquipmentArchives emEquipmentArchives)
+    {
+        List<EmEquipmentArchives> list = emEquipmentArchivesService.selectEmEquipmentArchivesList(emEquipmentArchives);
+        ExcelUtil<EmEquipmentArchives> util = new ExcelUtil<EmEquipmentArchives>(EmEquipmentArchives.class);
+        util.exportExcel(response, list, "璁惧妗f鏁版嵁");
+    }
+
+    /**
+     * 鑾峰彇璁惧妗f璇︾粏淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('em:equipmentArchives:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(emEquipmentArchivesService.selectEmEquipmentArchivesById(id));
+    }
+
+    /**
+     * 鏂板璁惧妗f
+     */
+    @PreAuthorize("@ss.hasPermi('em:equipmentArchives:add')")
+    @Log(title = "璁惧妗f", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody EmEquipmentArchives emEquipmentArchives)
+    {
+        return toAjax(emEquipmentArchivesService.insertEmEquipmentArchives(emEquipmentArchives));
+    }
+
+    /**
+     * 淇敼璁惧妗f
+     */
+    @PreAuthorize("@ss.hasPermi('em:equipmentArchives:edit')")
+    @Log(title = "璁惧妗f", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody EmEquipmentArchives emEquipmentArchives)
+    {
+        return toAjax(emEquipmentArchivesService.updateEmEquipmentArchives(emEquipmentArchives));
+    }
+
+    /**
+     * 鍒犻櫎璁惧妗f
+     */
+    @PreAuthorize("@ss.hasPermi('em:equipmentArchives:remove')")
+    @Log(title = "璁惧妗f", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(emEquipmentArchivesService.deleteEmEquipmentArchivesByIds(ids));
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/em/equipmentArchives/domain/EmEquipmentArchives.java b/jcdm-main/src/main/java/com/jcdm/main/em/equipmentArchives/domain/EmEquipmentArchives.java
new file mode 100644
index 0000000..b4f8c19
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/em/equipmentArchives/domain/EmEquipmentArchives.java
@@ -0,0 +1,287 @@
+package com.jcdm.main.em.equipmentArchives.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.core.domain.BaseEntity;
+
+/**
+ * 璁惧妗f瀵硅薄 em_equipment_archives
+ * 
+ * @author Yi
+ * @date 2023-12-26
+ */
+public class EmEquipmentArchives extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** ID */
+    private Long id;
+
+    /** 璁惧缂栫爜 */
+    @Excel(name = "璁惧缂栫爜")
+    private String equipmentCode;
+
+    /** 璁惧鍚嶇О */
+    @Excel(name = "璁惧鍚嶇О")
+    private String equipmentName;
+
+    /** 鍝佺墝 */
+    @Excel(name = "鍝佺墝")
+    private String equipmentBrand;
+
+    /** 瑙勬牸鍨嬪彿 */
+    @Excel(name = "瑙勬牸鍨嬪彿")
+    private String equipmentSpec;
+
+    /** 璁惧绫诲瀷ID */
+    @Excel(name = "璁惧绫诲瀷ID")
+    private Long equipmentTypeId;
+
+    /** 璁惧绫诲瀷缂栫爜 */
+    @Excel(name = "璁惧绫诲瀷缂栫爜")
+    private String equipmentTypeCode;
+
+    /** 璁惧绫诲瀷鍚嶇О */
+    @Excel(name = "璁惧绫诲瀷鍚嶇О")
+    private String equipmentTypeName;
+
+    /** 杞﹂棿缂栫爜 */
+    @Excel(name = "杞﹂棿缂栫爜")
+    private String workshopCode;
+
+    /** 浜х嚎缂栫爜 */
+    @Excel(name = "浜х嚎缂栫爜")
+    private String lineCode;
+
+    /** 宸ュ簭缂栫爜 */
+    @Excel(name = "宸ュ簭缂栫爜")
+    private String processesCode;
+    @Excel(name = "宸ュ簭鍚嶇О")
+    private String processesName;
+
+    /** 璁惧鐘舵�� */
+    @Excel(name = "璁惧鐘舵��")
+    private String status;
+
+    /** 鍒涘缓浜� */
+    @Excel(name = "鍒涘缓浜�")
+    private String createUser;
+
+    /** 鏇存柊浜� */
+    @Excel(name = "鏇存柊浜�")
+    private String updateUser;
+
+    /** 棰勭暀瀛楁1 */
+    @Excel(name = "棰勭暀瀛楁1")
+    private String spareField1;
+
+    /** 棰勭暀瀛楁2 */
+    @Excel(name = "棰勭暀瀛楁2")
+    private String spareField2;
+
+    /** 棰勭暀瀛楁3 */
+    @Excel(name = "棰勭暀瀛楁3")
+    private Long spareField3;
+
+    /** 棰勭暀瀛楁4 */
+    @Excel(name = "棰勭暀瀛楁4")
+    private Long spareField4;
+
+    public void setId(Long id) 
+    {
+        this.id = id;
+    }
+
+    public Long getId() 
+    {
+        return id;
+    }
+    public void setEquipmentCode(String equipmentCode) 
+    {
+        this.equipmentCode = equipmentCode;
+    }
+
+    public String getEquipmentCode() 
+    {
+        return equipmentCode;
+    }
+    public void setEquipmentName(String equipmentName) 
+    {
+        this.equipmentName = equipmentName;
+    }
+
+    public String getEquipmentName() 
+    {
+        return equipmentName;
+    }
+    public void setEquipmentBrand(String equipmentBrand) 
+    {
+        this.equipmentBrand = equipmentBrand;
+    }
+
+    public String getEquipmentBrand() 
+    {
+        return equipmentBrand;
+    }
+    public void setEquipmentSpec(String equipmentSpec) 
+    {
+        this.equipmentSpec = equipmentSpec;
+    }
+
+    public String getEquipmentSpec() 
+    {
+        return equipmentSpec;
+    }
+    public void setEquipmentTypeId(Long equipmentTypeId) 
+    {
+        this.equipmentTypeId = equipmentTypeId;
+    }
+
+    public Long getEquipmentTypeId() 
+    {
+        return equipmentTypeId;
+    }
+    public void setEquipmentTypeCode(String equipmentTypeCode) 
+    {
+        this.equipmentTypeCode = equipmentTypeCode;
+    }
+
+    public String getEquipmentTypeCode() 
+    {
+        return equipmentTypeCode;
+    }
+    public void setEquipmentTypeName(String equipmentTypeName) 
+    {
+        this.equipmentTypeName = equipmentTypeName;
+    }
+
+    public String getEquipmentTypeName() 
+    {
+        return equipmentTypeName;
+    }
+    public void setWorkshopCode(String workshopCode) 
+    {
+        this.workshopCode = workshopCode;
+    }
+
+    public String getWorkshopCode() 
+    {
+        return workshopCode;
+    }
+    public void setLineCode(String lineCode) 
+    {
+        this.lineCode = lineCode;
+    }
+
+    public String getLineCode() 
+    {
+        return lineCode;
+    }
+    public void setProcessesCode(String processesCode)
+    {
+        this.processesCode = processesCode;
+    }
+
+    public String getProcessesCode()
+    {
+        return processesCode;
+    }
+    public void setProcessesName(String processesName) {this.processesName = processesName; }
+
+    public String getProcessesName()
+    {
+        return processesName;
+    }
+    public void setStatus(String status)
+    {
+        this.status = status;
+    }
+
+    public String getStatus() 
+    {
+        return status;
+    }
+    public void setCreateUser(String createUser) 
+    {
+        this.createUser = createUser;
+    }
+
+    public String getCreateUser() 
+    {
+        return createUser;
+    }
+    public void setUpdateUser(String updateUser) 
+    {
+        this.updateUser = updateUser;
+    }
+
+    public String getUpdateUser() 
+    {
+        return updateUser;
+    }
+    public void setSpareField1(String spareField1) 
+    {
+        this.spareField1 = spareField1;
+    }
+
+    public String getSpareField1() 
+    {
+        return spareField1;
+    }
+    public void setSpareField2(String spareField2) 
+    {
+        this.spareField2 = spareField2;
+    }
+
+    public String getSpareField2() 
+    {
+        return spareField2;
+    }
+    public void setSpareField3(Long spareField3) 
+    {
+        this.spareField3 = spareField3;
+    }
+
+    public Long getSpareField3() 
+    {
+        return spareField3;
+    }
+    public void setSpareField4(Long spareField4) 
+    {
+        this.spareField4 = spareField4;
+    }
+
+    public Long getSpareField4() 
+    {
+        return spareField4;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("equipmentCode", getEquipmentCode())
+            .append("equipmentName", getEquipmentName())
+            .append("equipmentBrand", getEquipmentBrand())
+            .append("equipmentSpec", getEquipmentSpec())
+            .append("equipmentTypeId", getEquipmentTypeId())
+            .append("equipmentTypeCode", getEquipmentTypeCode())
+            .append("equipmentTypeName", getEquipmentTypeName())
+            .append("workshopCode", getWorkshopCode())
+            .append("lineCode", getLineCode())
+            .append("processesCode", getProcessesCode())
+            .append("processesName", getProcessesName())
+            .append("status", getStatus())
+            .append("remark", getRemark())
+            .append("createUser", getCreateUser())
+            .append("createTime", getCreateTime())
+            .append("updateUser", getUpdateUser())
+            .append("updateTime", getUpdateTime())
+            .append("spareField1", getSpareField1())
+            .append("spareField2", getSpareField2())
+            .append("spareField3", getSpareField3())
+            .append("spareField4", getSpareField4())
+            .toString();
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/em/equipmentArchives/mapper/EmEquipmentArchivesMapper.java b/jcdm-main/src/main/java/com/jcdm/main/em/equipmentArchives/mapper/EmEquipmentArchivesMapper.java
new file mode 100644
index 0000000..6476cce
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/em/equipmentArchives/mapper/EmEquipmentArchivesMapper.java
@@ -0,0 +1,61 @@
+package com.jcdm.main.em.equipmentArchives.mapper;
+
+import java.util.List;
+import com.jcdm.main.em.equipmentArchives.domain.EmEquipmentArchives;
+
+/**
+ * 璁惧妗fMapper鎺ュ彛
+ * 
+ * @author Yi
+ * @date 2023-12-26
+ */
+public interface EmEquipmentArchivesMapper 
+{
+    /**
+     * 鏌ヨ璁惧妗f
+     * 
+     * @param id 璁惧妗f涓婚敭
+     * @return 璁惧妗f
+     */
+    public EmEquipmentArchives selectEmEquipmentArchivesById(Long id);
+
+    /**
+     * 鏌ヨ璁惧妗f鍒楄〃
+     * 
+     * @param emEquipmentArchives 璁惧妗f
+     * @return 璁惧妗f闆嗗悎
+     */
+    public List<EmEquipmentArchives> selectEmEquipmentArchivesList(EmEquipmentArchives emEquipmentArchives);
+
+    /**
+     * 鏂板璁惧妗f
+     * 
+     * @param emEquipmentArchives 璁惧妗f
+     * @return 缁撴灉
+     */
+    public int insertEmEquipmentArchives(EmEquipmentArchives emEquipmentArchives);
+
+    /**
+     * 淇敼璁惧妗f
+     * 
+     * @param emEquipmentArchives 璁惧妗f
+     * @return 缁撴灉
+     */
+    public int updateEmEquipmentArchives(EmEquipmentArchives emEquipmentArchives);
+
+    /**
+     * 鍒犻櫎璁惧妗f
+     * 
+     * @param id 璁惧妗f涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteEmEquipmentArchivesById(Long id);
+
+    /**
+     * 鎵归噺鍒犻櫎璁惧妗f
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteEmEquipmentArchivesByIds(Long[] ids);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/em/equipmentArchives/service/IEmEquipmentArchivesService.java b/jcdm-main/src/main/java/com/jcdm/main/em/equipmentArchives/service/IEmEquipmentArchivesService.java
new file mode 100644
index 0000000..03b5340
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/em/equipmentArchives/service/IEmEquipmentArchivesService.java
@@ -0,0 +1,61 @@
+package com.jcdm.main.em.equipmentArchives.service;
+
+import java.util.List;
+import com.jcdm.main.em.equipmentArchives.domain.EmEquipmentArchives;
+
+/**
+ * 璁惧妗fService鎺ュ彛
+ * 
+ * @author Yi
+ * @date 2023-12-26
+ */
+public interface IEmEquipmentArchivesService 
+{
+    /**
+     * 鏌ヨ璁惧妗f
+     * 
+     * @param id 璁惧妗f涓婚敭
+     * @return 璁惧妗f
+     */
+    public EmEquipmentArchives selectEmEquipmentArchivesById(Long id);
+
+    /**
+     * 鏌ヨ璁惧妗f鍒楄〃
+     * 
+     * @param emEquipmentArchives 璁惧妗f
+     * @return 璁惧妗f闆嗗悎
+     */
+    public List<EmEquipmentArchives> selectEmEquipmentArchivesList(EmEquipmentArchives emEquipmentArchives);
+
+    /**
+     * 鏂板璁惧妗f
+     * 
+     * @param emEquipmentArchives 璁惧妗f
+     * @return 缁撴灉
+     */
+    public int insertEmEquipmentArchives(EmEquipmentArchives emEquipmentArchives);
+
+    /**
+     * 淇敼璁惧妗f
+     * 
+     * @param emEquipmentArchives 璁惧妗f
+     * @return 缁撴灉
+     */
+    public int updateEmEquipmentArchives(EmEquipmentArchives emEquipmentArchives);
+
+    /**
+     * 鎵归噺鍒犻櫎璁惧妗f
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑璁惧妗f涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteEmEquipmentArchivesByIds(Long[] ids);
+
+    /**
+     * 鍒犻櫎璁惧妗f淇℃伅
+     * 
+     * @param id 璁惧妗f涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteEmEquipmentArchivesById(Long id);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/em/equipmentArchives/service/impl/EmEquipmentArchivesServiceImpl.java b/jcdm-main/src/main/java/com/jcdm/main/em/equipmentArchives/service/impl/EmEquipmentArchivesServiceImpl.java
new file mode 100644
index 0000000..7c8040a
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/em/equipmentArchives/service/impl/EmEquipmentArchivesServiceImpl.java
@@ -0,0 +1,96 @@
+package com.jcdm.main.em.equipmentArchives.service.impl;
+
+import java.util.List;
+import com.jcdm.common.utils.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.jcdm.main.em.equipmentArchives.mapper.EmEquipmentArchivesMapper;
+import com.jcdm.main.em.equipmentArchives.domain.EmEquipmentArchives;
+import com.jcdm.main.em.equipmentArchives.service.IEmEquipmentArchivesService;
+
+/**
+ * 璁惧妗fService涓氬姟灞傚鐞�
+ * 
+ * @author Yi
+ * @date 2023-12-26
+ */
+@Service
+public class EmEquipmentArchivesServiceImpl implements IEmEquipmentArchivesService 
+{
+    @Autowired
+    private EmEquipmentArchivesMapper emEquipmentArchivesMapper;
+
+    /**
+     * 鏌ヨ璁惧妗f
+     * 
+     * @param id 璁惧妗f涓婚敭
+     * @return 璁惧妗f
+     */
+    @Override
+    public EmEquipmentArchives selectEmEquipmentArchivesById(Long id)
+    {
+        return emEquipmentArchivesMapper.selectEmEquipmentArchivesById(id);
+    }
+
+    /**
+     * 鏌ヨ璁惧妗f鍒楄〃
+     * 
+     * @param emEquipmentArchives 璁惧妗f
+     * @return 璁惧妗f
+     */
+    @Override
+    public List<EmEquipmentArchives> selectEmEquipmentArchivesList(EmEquipmentArchives emEquipmentArchives)
+    {
+        return emEquipmentArchivesMapper.selectEmEquipmentArchivesList(emEquipmentArchives);
+    }
+
+    /**
+     * 鏂板璁惧妗f
+     * 
+     * @param emEquipmentArchives 璁惧妗f
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertEmEquipmentArchives(EmEquipmentArchives emEquipmentArchives)
+    {
+        emEquipmentArchives.setCreateTime(DateUtils.getNowDate());
+        return emEquipmentArchivesMapper.insertEmEquipmentArchives(emEquipmentArchives);
+    }
+
+    /**
+     * 淇敼璁惧妗f
+     * 
+     * @param emEquipmentArchives 璁惧妗f
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateEmEquipmentArchives(EmEquipmentArchives emEquipmentArchives)
+    {
+        emEquipmentArchives.setUpdateTime(DateUtils.getNowDate());
+        return emEquipmentArchivesMapper.updateEmEquipmentArchives(emEquipmentArchives);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎璁惧妗f
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑璁惧妗f涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteEmEquipmentArchivesByIds(Long[] ids)
+    {
+        return emEquipmentArchivesMapper.deleteEmEquipmentArchivesByIds(ids);
+    }
+
+    /**
+     * 鍒犻櫎璁惧妗f淇℃伅
+     * 
+     * @param id 璁惧妗f涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteEmEquipmentArchivesById(Long id)
+    {
+        return emEquipmentArchivesMapper.deleteEmEquipmentArchivesById(id);
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/em/equipmentStatus/controller/EmEquipmentStatusController.java b/jcdm-main/src/main/java/com/jcdm/main/em/equipmentStatus/controller/EmEquipmentStatusController.java
new file mode 100644
index 0000000..5307d92
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/em/equipmentStatus/controller/EmEquipmentStatusController.java
@@ -0,0 +1,104 @@
+package com.jcdm.main.em.equipmentStatus.controller;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.main.em.equipmentStatus.domain.EmEquipmentStatus;
+import com.jcdm.main.em.equipmentStatus.service.IEmEquipmentStatusService;
+import com.jcdm.common.utils.poi.ExcelUtil;
+import com.jcdm.common.core.page.TableDataInfo;
+
+/**
+ * 璁惧鐘舵�丆ontroller
+ * 
+ * @author ruimin
+ * @date 2023-12-27
+ */
+@RestController
+@RequestMapping("/em/equipmentStatus")
+public class EmEquipmentStatusController extends BaseController
+{
+    @Autowired
+    private IEmEquipmentStatusService emEquipmentStatusService;
+
+    /**
+     * 鏌ヨ璁惧鐘舵�佸垪琛�
+     */
+    @PreAuthorize("@ss.hasPermi('em:equipmentStatus:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(EmEquipmentStatus emEquipmentStatus)
+    {
+        startPage();
+        List<EmEquipmentStatus> list = emEquipmentStatusService.selectEmEquipmentStatusList(emEquipmentStatus);
+        return getDataTable(list);
+    }
+
+    /**
+     * 瀵煎嚭璁惧鐘舵�佸垪琛�
+     */
+    @PreAuthorize("@ss.hasPermi('em:equipmentStatus:export')")
+    @Log(title = "璁惧鐘舵��", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, EmEquipmentStatus emEquipmentStatus)
+    {
+        List<EmEquipmentStatus> list = emEquipmentStatusService.selectEmEquipmentStatusList(emEquipmentStatus);
+        ExcelUtil<EmEquipmentStatus> util = new ExcelUtil<EmEquipmentStatus>(EmEquipmentStatus.class);
+        util.exportExcel(response, list, "璁惧鐘舵�佹暟鎹�");
+    }
+
+    /**
+     * 鑾峰彇璁惧鐘舵�佽缁嗕俊鎭�
+     */
+    @PreAuthorize("@ss.hasPermi('em:equipmentStatus:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(emEquipmentStatusService.selectEmEquipmentStatusById(id));
+    }
+
+    /**
+     * 鏂板璁惧鐘舵��
+     */
+    @PreAuthorize("@ss.hasPermi('em:equipmentStatus:add')")
+    @Log(title = "璁惧鐘舵��", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody EmEquipmentStatus emEquipmentStatus)
+    {
+        return toAjax(emEquipmentStatusService.insertEmEquipmentStatus(emEquipmentStatus));
+    }
+
+    /**
+     * 淇敼璁惧鐘舵��
+     */
+    @PreAuthorize("@ss.hasPermi('em:equipmentStatus:edit')")
+    @Log(title = "璁惧鐘舵��", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody EmEquipmentStatus emEquipmentStatus)
+    {
+        return toAjax(emEquipmentStatusService.updateEmEquipmentStatus(emEquipmentStatus));
+    }
+
+    /**
+     * 鍒犻櫎璁惧鐘舵��
+     */
+    @PreAuthorize("@ss.hasPermi('em:equipmentStatus:remove')")
+    @Log(title = "璁惧鐘舵��", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(emEquipmentStatusService.deleteEmEquipmentStatusByIds(ids));
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/em/equipmentStatus/domain/EmEquipmentStatus.java b/jcdm-main/src/main/java/com/jcdm/main/em/equipmentStatus/domain/EmEquipmentStatus.java
new file mode 100644
index 0000000..93f6767
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/em/equipmentStatus/domain/EmEquipmentStatus.java
@@ -0,0 +1,162 @@
+package com.jcdm.main.em.equipmentStatus.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.core.domain.BaseEntity;
+
+/**
+ * 璁惧鐘舵�佸璞� em_equipment_status
+ * 
+ * @author ruimin
+ * @date 2023-12-27
+ */
+public class EmEquipmentStatus extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** ID */
+    private Long id;
+
+    /** 璁惧缂栧彿 */
+    @Excel(name = "璁惧缂栧彿")
+    private String equipmentNo;
+
+    /** 璁惧鍚嶇О */
+    @Excel(name = "璁惧鍚嶇О")
+    private String equipmentName;
+
+    /** 杞﹂棿缂栧彿 */
+    @Excel(name = "杞﹂棿缂栧彿")
+    private String workshopCode;
+
+    /** 浜х嚎缂栧彿 */
+    @Excel(name = "浜х嚎缂栧彿")
+    private String productionLineCode;
+
+    /** 宸ュ簭缂栧彿 */
+    @Excel(name = "宸ュ簭缂栧彿")
+    private String processesCode;
+
+    /** 璁惧鐘舵��(1杩愯浆2寰呮満3鏁呴殰) */
+    @Excel(name = "璁惧鐘舵��(1杩愯浆2寰呮満3鏁呴殰)")
+    private String eqStatus;
+
+    /** 棰勭暀瀛楁1 */
+    private String spareField1;
+
+    /** 棰勭暀瀛楁2 */
+    private String spareField2;
+
+    /** 澶囨敞 */
+    @Excel(name = "澶囨敞")
+    private String remarks;
+
+    public void setId(Long id) 
+    {
+        this.id = id;
+    }
+
+    public Long getId() 
+    {
+        return id;
+    }
+    public void setEquipmentNo(String equipmentNo) 
+    {
+        this.equipmentNo = equipmentNo;
+    }
+
+    public String getEquipmentNo() 
+    {
+        return equipmentNo;
+    }
+    public void setEquipmentName(String equipmentName) 
+    {
+        this.equipmentName = equipmentName;
+    }
+
+    public String getEquipmentName() 
+    {
+        return equipmentName;
+    }
+    public void setWorkshopCode(String workshopCode) 
+    {
+        this.workshopCode = workshopCode;
+    }
+
+    public String getWorkshopCode() 
+    {
+        return workshopCode;
+    }
+    public void setProductionLineCode(String productionLineCode) 
+    {
+        this.productionLineCode = productionLineCode;
+    }
+
+    public String getProductionLineCode() 
+    {
+        return productionLineCode;
+    }
+    public void setProcessesCode(String processesCode) 
+    {
+        this.processesCode = processesCode;
+    }
+
+    public String getProcessesCode() 
+    {
+        return processesCode;
+    }
+    public void setEqStatus(String eqStatus) 
+    {
+        this.eqStatus = eqStatus;
+    }
+
+    public String getEqStatus() 
+    {
+        return eqStatus;
+    }
+    public void setSpareField1(String spareField1) 
+    {
+        this.spareField1 = spareField1;
+    }
+
+    public String getSpareField1() 
+    {
+        return spareField1;
+    }
+    public void setSpareField2(String spareField2) 
+    {
+        this.spareField2 = spareField2;
+    }
+
+    public String getSpareField2() 
+    {
+        return spareField2;
+    }
+    public void setRemarks(String remarks) 
+    {
+        this.remarks = remarks;
+    }
+
+    public String getRemarks() 
+    {
+        return remarks;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("equipmentNo", getEquipmentNo())
+            .append("equipmentName", getEquipmentName())
+            .append("workshopCode", getWorkshopCode())
+            .append("productionLineCode", getProductionLineCode())
+            .append("processesCode", getProcessesCode())
+            .append("eqStatus", getEqStatus())
+            .append("spareField1", getSpareField1())
+            .append("spareField2", getSpareField2())
+            .append("remarks", getRemarks())
+            .append("updateTime", getUpdateTime())
+            .toString();
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/em/equipmentStatus/mapper/EmEquipmentStatusMapper.java b/jcdm-main/src/main/java/com/jcdm/main/em/equipmentStatus/mapper/EmEquipmentStatusMapper.java
new file mode 100644
index 0000000..4431caf
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/em/equipmentStatus/mapper/EmEquipmentStatusMapper.java
@@ -0,0 +1,61 @@
+package com.jcdm.main.em.equipmentStatus.mapper;
+
+import java.util.List;
+import com.jcdm.main.em.equipmentStatus.domain.EmEquipmentStatus;
+
+/**
+ * 璁惧鐘舵�丮apper鎺ュ彛
+ * 
+ * @author ruimin
+ * @date 2023-12-27
+ */
+public interface EmEquipmentStatusMapper 
+{
+    /**
+     * 鏌ヨ璁惧鐘舵��
+     * 
+     * @param id 璁惧鐘舵�佷富閿�
+     * @return 璁惧鐘舵��
+     */
+    public EmEquipmentStatus selectEmEquipmentStatusById(Long id);
+
+    /**
+     * 鏌ヨ璁惧鐘舵�佸垪琛�
+     * 
+     * @param emEquipmentStatus 璁惧鐘舵��
+     * @return 璁惧鐘舵�侀泦鍚�
+     */
+    public List<EmEquipmentStatus> selectEmEquipmentStatusList(EmEquipmentStatus emEquipmentStatus);
+
+    /**
+     * 鏂板璁惧鐘舵��
+     * 
+     * @param emEquipmentStatus 璁惧鐘舵��
+     * @return 缁撴灉
+     */
+    public int insertEmEquipmentStatus(EmEquipmentStatus emEquipmentStatus);
+
+    /**
+     * 淇敼璁惧鐘舵��
+     * 
+     * @param emEquipmentStatus 璁惧鐘舵��
+     * @return 缁撴灉
+     */
+    public int updateEmEquipmentStatus(EmEquipmentStatus emEquipmentStatus);
+
+    /**
+     * 鍒犻櫎璁惧鐘舵��
+     * 
+     * @param id 璁惧鐘舵�佷富閿�
+     * @return 缁撴灉
+     */
+    public int deleteEmEquipmentStatusById(Long id);
+
+    /**
+     * 鎵归噺鍒犻櫎璁惧鐘舵��
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteEmEquipmentStatusByIds(Long[] ids);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/em/equipmentStatus/service/IEmEquipmentStatusService.java b/jcdm-main/src/main/java/com/jcdm/main/em/equipmentStatus/service/IEmEquipmentStatusService.java
new file mode 100644
index 0000000..a93b2ba
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/em/equipmentStatus/service/IEmEquipmentStatusService.java
@@ -0,0 +1,61 @@
+package com.jcdm.main.em.equipmentStatus.service;
+
+import java.util.List;
+import com.jcdm.main.em.equipmentStatus.domain.EmEquipmentStatus;
+
+/**
+ * 璁惧鐘舵�丼ervice鎺ュ彛
+ * 
+ * @author ruimin
+ * @date 2023-12-27
+ */
+public interface IEmEquipmentStatusService 
+{
+    /**
+     * 鏌ヨ璁惧鐘舵��
+     * 
+     * @param id 璁惧鐘舵�佷富閿�
+     * @return 璁惧鐘舵��
+     */
+    public EmEquipmentStatus selectEmEquipmentStatusById(Long id);
+
+    /**
+     * 鏌ヨ璁惧鐘舵�佸垪琛�
+     * 
+     * @param emEquipmentStatus 璁惧鐘舵��
+     * @return 璁惧鐘舵�侀泦鍚�
+     */
+    public List<EmEquipmentStatus> selectEmEquipmentStatusList(EmEquipmentStatus emEquipmentStatus);
+
+    /**
+     * 鏂板璁惧鐘舵��
+     * 
+     * @param emEquipmentStatus 璁惧鐘舵��
+     * @return 缁撴灉
+     */
+    public int insertEmEquipmentStatus(EmEquipmentStatus emEquipmentStatus);
+
+    /**
+     * 淇敼璁惧鐘舵��
+     * 
+     * @param emEquipmentStatus 璁惧鐘舵��
+     * @return 缁撴灉
+     */
+    public int updateEmEquipmentStatus(EmEquipmentStatus emEquipmentStatus);
+
+    /**
+     * 鎵归噺鍒犻櫎璁惧鐘舵��
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑璁惧鐘舵�佷富閿泦鍚�
+     * @return 缁撴灉
+     */
+    public int deleteEmEquipmentStatusByIds(Long[] ids);
+
+    /**
+     * 鍒犻櫎璁惧鐘舵�佷俊鎭�
+     * 
+     * @param id 璁惧鐘舵�佷富閿�
+     * @return 缁撴灉
+     */
+    public int deleteEmEquipmentStatusById(Long id);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/em/equipmentStatus/service/impl/EmEquipmentStatusServiceImpl.java b/jcdm-main/src/main/java/com/jcdm/main/em/equipmentStatus/service/impl/EmEquipmentStatusServiceImpl.java
new file mode 100644
index 0000000..1e0334f
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/em/equipmentStatus/service/impl/EmEquipmentStatusServiceImpl.java
@@ -0,0 +1,95 @@
+package com.jcdm.main.em.equipmentStatus.service.impl;
+
+import java.util.List;
+import com.jcdm.common.utils.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.jcdm.main.em.equipmentStatus.mapper.EmEquipmentStatusMapper;
+import com.jcdm.main.em.equipmentStatus.domain.EmEquipmentStatus;
+import com.jcdm.main.em.equipmentStatus.service.IEmEquipmentStatusService;
+
+/**
+ * 璁惧鐘舵�丼ervice涓氬姟灞傚鐞�
+ * 
+ * @author ruimin
+ * @date 2023-12-27
+ */
+@Service
+public class EmEquipmentStatusServiceImpl implements IEmEquipmentStatusService 
+{
+    @Autowired
+    private EmEquipmentStatusMapper emEquipmentStatusMapper;
+
+    /**
+     * 鏌ヨ璁惧鐘舵��
+     * 
+     * @param id 璁惧鐘舵�佷富閿�
+     * @return 璁惧鐘舵��
+     */
+    @Override
+    public EmEquipmentStatus selectEmEquipmentStatusById(Long id)
+    {
+        return emEquipmentStatusMapper.selectEmEquipmentStatusById(id);
+    }
+
+    /**
+     * 鏌ヨ璁惧鐘舵�佸垪琛�
+     * 
+     * @param emEquipmentStatus 璁惧鐘舵��
+     * @return 璁惧鐘舵��
+     */
+    @Override
+    public List<EmEquipmentStatus> selectEmEquipmentStatusList(EmEquipmentStatus emEquipmentStatus)
+    {
+        return emEquipmentStatusMapper.selectEmEquipmentStatusList(emEquipmentStatus);
+    }
+
+    /**
+     * 鏂板璁惧鐘舵��
+     * 
+     * @param emEquipmentStatus 璁惧鐘舵��
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertEmEquipmentStatus(EmEquipmentStatus emEquipmentStatus)
+    {
+        return emEquipmentStatusMapper.insertEmEquipmentStatus(emEquipmentStatus);
+    }
+
+    /**
+     * 淇敼璁惧鐘舵��
+     * 
+     * @param emEquipmentStatus 璁惧鐘舵��
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateEmEquipmentStatus(EmEquipmentStatus emEquipmentStatus)
+    {
+        emEquipmentStatus.setUpdateTime(DateUtils.getNowDate());
+        return emEquipmentStatusMapper.updateEmEquipmentStatus(emEquipmentStatus);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎璁惧鐘舵��
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑璁惧鐘舵�佷富閿�
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteEmEquipmentStatusByIds(Long[] ids)
+    {
+        return emEquipmentStatusMapper.deleteEmEquipmentStatusByIds(ids);
+    }
+
+    /**
+     * 鍒犻櫎璁惧鐘舵�佷俊鎭�
+     * 
+     * @param id 璁惧鐘舵�佷富閿�
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteEmEquipmentStatusById(Long id)
+    {
+        return emEquipmentStatusMapper.deleteEmEquipmentStatusById(id);
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/om/productionOrde/controller/OmProductionOrdeInfoController.java b/jcdm-main/src/main/java/com/jcdm/main/om/productionOrde/controller/OmProductionOrdeInfoController.java
new file mode 100644
index 0000000..63a195d
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/om/productionOrde/controller/OmProductionOrdeInfoController.java
@@ -0,0 +1,114 @@
+package com.jcdm.main.om.productionOrde.controller;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import com.jcdm.main.om.productionOrde.domain.OmProductionOrdeInfo;
+import com.jcdm.main.om.productionOrde.service.IOmProductionOrdeInfoService;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.common.utils.poi.ExcelUtil;
+import com.jcdm.common.core.page.TableDataInfo;
+
+/**
+ * 鐢熶骇宸ュ崟Controller
+ * 
+ * @author ruimin
+ * @date 2023-12-11
+ */
+@RestController
+@RequestMapping("/om/productionOrde")
+public class OmProductionOrdeInfoController extends BaseController
+{
+    @Autowired
+    private IOmProductionOrdeInfoService omProductionOrdeInfoService;
+
+    /**
+     * 鏌ヨ鐢熶骇宸ュ崟鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('om:productionOrde:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(OmProductionOrdeInfo omProductionOrdeInfo)
+    {
+        startPage();
+        List<OmProductionOrdeInfo> list = omProductionOrdeInfoService.selectOmProductionOrdeInfoList(omProductionOrdeInfo);
+        return getDataTable(list);
+    }
+
+    /**
+     * 瀵煎嚭鐢熶骇宸ュ崟鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('om:productionOrde:export')")
+    @Log(title = "鐢熶骇宸ュ崟", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, OmProductionOrdeInfo omProductionOrdeInfo)
+    {
+        List<OmProductionOrdeInfo> list = omProductionOrdeInfoService.selectOmProductionOrdeInfoList(omProductionOrdeInfo);
+        ExcelUtil<OmProductionOrdeInfo> util = new ExcelUtil<OmProductionOrdeInfo>(OmProductionOrdeInfo.class);
+        util.exportExcel(response, list, "鐢熶骇宸ュ崟鏁版嵁");
+    }
+
+    /**
+     * 鑾峰彇鐢熶骇宸ュ崟璇︾粏淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('om:productionOrde:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(omProductionOrdeInfoService.selectOmProductionOrdeInfoById(id));
+    }
+
+    /**
+     * 鏂板鐢熶骇宸ュ崟
+     */
+    @PreAuthorize("@ss.hasPermi('om:productionOrde:add')")
+    @Log(title = "鐢熶骇宸ュ崟", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody OmProductionOrdeInfo omProductionOrdeInfo)
+    {
+        return toAjax(omProductionOrdeInfoService.insertOmProductionOrdeInfo(omProductionOrdeInfo));
+    }
+
+    /**
+     * 淇敼鐢熶骇宸ュ崟
+     */
+    @PreAuthorize("@ss.hasPermi('om:productionOrde:edit')")
+    @Log(title = "鐢熶骇宸ュ崟", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody OmProductionOrdeInfo omProductionOrdeInfo)
+    {
+        return toAjax(omProductionOrdeInfoService.updateOmProductionOrdeInfo(omProductionOrdeInfo));
+    }
+
+    /**
+     * 鍒犻櫎鐢熶骇宸ュ崟
+     */
+    @PreAuthorize("@ss.hasPermi('om:productionOrde:remove')")
+    @Log(title = "鐢熶骇宸ュ崟", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(omProductionOrdeInfoService.deleteOmProductionOrdeInfoByIds(ids));
+    }
+
+    /**
+     * table鍒椾笂绉讳笅绉�
+     */
+    @Log(title = "鐢熶骇宸ュ崟", businessType = BusinessType.DELETE)
+    @GetMapping("/upDownMove")
+    public AjaxResult upDownMove(OmProductionOrdeInfo omProductionOrdeInfo)
+    {
+        return omProductionOrdeInfoService.upDownMove(omProductionOrdeInfo);
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/om/productionOrde/domain/OmProductionOrdeInfo.java b/jcdm-main/src/main/java/com/jcdm/main/om/productionOrde/domain/OmProductionOrdeInfo.java
new file mode 100644
index 0000000..6a51915
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/om/productionOrde/domain/OmProductionOrdeInfo.java
@@ -0,0 +1,557 @@
+package com.jcdm.main.om.productionOrde.domain;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.core.domain.BaseEntity;
+
+/**
+ * 鐢熶骇宸ュ崟瀵硅薄 om_production_orde_info
+ * 
+ * @author ruimin
+ * @date 2023-12-11
+ */
+public class OmProductionOrdeInfo extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** ID */
+    private Long id;
+
+    /** 鐢熶骇宸ュ崟鍙� */
+    @Excel(name = "鐢熶骇宸ュ崟鍙�")
+    private String workOrderNo;
+
+    /** 璁㈠崟缂栧彿 */
+    @Excel(name = "璁㈠崟缂栧彿")
+    private String salesOrderCode;
+
+    /** 浜у搧缂栧彿 */
+    @Excel(name = "浜у搧缂栧彿")
+    private String productCode;
+
+    /** 浜у搧鍚嶇О */
+    @Excel(name = "浜у搧鍚嶇О")
+    private String productName;
+
+    /** 杞﹂棿缂栧彿 */
+    @Excel(name = "杞﹂棿缂栧彿")
+    private String workshopCode;
+
+    /** 浜х嚎缂栧彿 */
+    @Excel(name = "浜х嚎缂栧彿")
+    private String lineCode;
+
+    /** 宸ヨ壓娴佺▼ */
+    @Excel(name = "宸ヨ壓娴佺▼")
+    private String routeCode;
+
+    /** 浜у搧BOM */
+    @Excel(name = "浜у搧BOM")
+    private String bomCode;
+
+    /** 宸ヨ壓閰嶆柟 */
+    @Excel(name = "宸ヨ壓閰嶆柟")
+    private String recipeCode;
+
+    /** 璁″垝鏁伴噺 */
+    @Excel(name = "璁″垝鏁伴噺")
+    private Long planQty;
+
+    /** 瀹為檯鏁伴噺 */
+    @Excel(name = "瀹為檯鏁伴噺")
+    private Long actualQty;
+
+    /** 涓嶈壇鏁伴噺 */
+    @Excel(name = "涓嶈壇鏁伴噺")
+    private Long badQty;
+
+    /** 鎶ュ簾鏁伴噺 */
+    @Excel(name = "鎶ュ簾鏁伴噺")
+    private Long scrapQty;
+
+    /** 杩斾慨鏁伴噺 */
+    @Excel(name = "杩斾慨鏁伴噺")
+    private Long repairQty;
+
+    /** 瀹為檯涓婄嚎鏁伴噺 */
+    @Excel(name = "瀹為檯涓婄嚎鏁伴噺")
+    private Long actualOnlineQty;
+
+    /** 涓婄嚎瀹屽伐鏍囪 */
+    private String onlineCompletionMark;
+
+    private Long frontEndId;
+
+    /** 闇�姹傛棩鏈� */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "闇�姹傛棩鏈�", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date demandDate;
+
+    /** 璁″垝寮�濮嬫椂闂� */
+    @Excel(name = "璁″垝寮�濮嬫椂闂�")
+    private String planStartTime;
+
+    /** 璁″垝缁撴潫鏃堕棿 */
+    @Excel(name = "璁″垝缁撴潫鏃堕棿")
+    private String planEndTime;
+
+    /** 瀹為檯寮�濮嬫椂闂� */
+    @Excel(name = "瀹為檯寮�濮嬫椂闂�")
+    private String actualStartTime;
+
+    /** 瀹為檯缁撴潫鏃堕棿 */
+    @Excel(name = "瀹為檯缁撴潫鏃堕棿")
+    private String actualEndTime;
+
+    /** 椤哄簭鍙� */
+    @Excel(name = "椤哄簭鍙�")
+    private Long serialNumber;
+
+    /** 宸ュ崟鐘舵�侊紙1鍒涘缓銆�2宸插彂甯冦��3鐢熶骇涓��4宸插喕缁撱��5宸插畬宸ャ��6宸插叧闂級 */
+    @Excel(name = "宸ュ崟鐘舵��", readConverterExp = "1=鍒涘缓銆�2宸插彂甯冦��3鐢熶骇涓��4宸插喕缁撱��5宸插畬宸ャ��6宸插叧闂�")
+    private String orderStatus;
+
+    /** 鍒涘缓浜� */
+    @Excel(name = "鍒涘缓浜�")
+    private String createUser;
+
+    /** 淇敼浜� */
+    @Excel(name = "淇敼浜�")
+    private String updateUser;
+
+    /** 澶囨敞 */
+    @Excel(name = "澶囨敞")
+    private String remarks;
+
+    /** 娴佹按鍙� */
+    @Excel(name = "娴佹按鍙�")
+    private String streamNumber;
+
+    /** 瀹㈡埛 */
+    @Excel(name = "瀹㈡埛")
+    private String custom;
+
+    /** 甯傚満鍖哄煙缂栫爜 */
+    @Excel(name = "甯傚満鍖哄煙缂栫爜")
+    private String marketAreaCode;
+
+    /** 杞欢鐗堟湰缂栫爜 */
+    @Excel(name = "杞欢鐗堟湰缂栫爜")
+    private String softwareVersionCode;
+
+    /** 浜у搧鍏徃缂栫爜 */
+    @Excel(name = "浜у搧鍏徃缂栫爜")
+    private String productCompanyCode;
+
+    /** 棰勭暀瀛楁1 */
+    private String spareField1;
+
+    /** 棰勭暀瀛楁2 */
+    private String spareField2;
+
+    /** 棰勭暀瀛楁3 */
+    private String spareField3;
+
+    /** 棰勭暀瀛楁4 */
+    private String spareField4;
+
+    private Long[] idNums;
+
+    private String flag;
+
+    public String getFlag() {
+        return flag;
+    }
+
+    public void setFlag(String flag) {
+        this.flag = flag;
+    }
+
+    public Long[] getIdNums() {
+        return idNums;
+    }
+
+    public void setIdNums(Long[] idNums) {
+        this.idNums = idNums;
+    }
+
+    public Long getFrontEndId() {
+        return frontEndId;
+    }
+
+    public void setFrontEndId(Long frontEndId) {
+        this.frontEndId = frontEndId;
+    }
+
+    public void setId(Long id)
+    {
+        this.id = id;
+    }
+
+    public Long getId() 
+    {
+        return id;
+    }
+    public void setWorkOrderNo(String workOrderNo) 
+    {
+        this.workOrderNo = workOrderNo;
+    }
+
+    public String getWorkOrderNo() 
+    {
+        return workOrderNo;
+    }
+    public void setSalesOrderCode(String salesOrderCode) 
+    {
+        this.salesOrderCode = salesOrderCode;
+    }
+
+    public String getSalesOrderCode() 
+    {
+        return salesOrderCode;
+    }
+    public void setProductCode(String productCode) 
+    {
+        this.productCode = productCode;
+    }
+
+    public String getProductCode() 
+    {
+        return productCode;
+    }
+    public void setProductName(String productName) 
+    {
+        this.productName = productName;
+    }
+
+    public String getProductName() 
+    {
+        return productName;
+    }
+    public void setWorkshopCode(String workshopCode) 
+    {
+        this.workshopCode = workshopCode;
+    }
+
+    public String getWorkshopCode() 
+    {
+        return workshopCode;
+    }
+    public void setLineCode(String lineCode) 
+    {
+        this.lineCode = lineCode;
+    }
+
+    public String getLineCode() 
+    {
+        return lineCode;
+    }
+    public void setRouteCode(String routeCode) 
+    {
+        this.routeCode = routeCode;
+    }
+
+    public String getRouteCode() 
+    {
+        return routeCode;
+    }
+    public void setBomCode(String bomCode) 
+    {
+        this.bomCode = bomCode;
+    }
+
+    public String getBomCode() 
+    {
+        return bomCode;
+    }
+    public void setRecipeCode(String recipeCode) 
+    {
+        this.recipeCode = recipeCode;
+    }
+
+    public String getRecipeCode() 
+    {
+        return recipeCode;
+    }
+    public void setPlanQty(Long planQty) 
+    {
+        this.planQty = planQty;
+    }
+
+    public Long getPlanQty() 
+    {
+        return planQty;
+    }
+    public void setActualQty(Long actualQty) 
+    {
+        this.actualQty = actualQty;
+    }
+
+    public Long getActualQty() 
+    {
+        return actualQty;
+    }
+    public void setBadQty(Long badQty) 
+    {
+        this.badQty = badQty;
+    }
+
+    public Long getBadQty() 
+    {
+        return badQty;
+    }
+    public void setScrapQty(Long scrapQty) 
+    {
+        this.scrapQty = scrapQty;
+    }
+
+    public Long getScrapQty() 
+    {
+        return scrapQty;
+    }
+    public void setRepairQty(Long repairQty) 
+    {
+        this.repairQty = repairQty;
+    }
+
+    public Long getRepairQty() 
+    {
+        return repairQty;
+    }
+    public void setActualOnlineQty(Long actualOnlineQty) 
+    {
+        this.actualOnlineQty = actualOnlineQty;
+    }
+
+    public Long getActualOnlineQty() 
+    {
+        return actualOnlineQty;
+    }
+    public void setOnlineCompletionMark(String onlineCompletionMark) 
+    {
+        this.onlineCompletionMark = onlineCompletionMark;
+    }
+
+    public String getOnlineCompletionMark() 
+    {
+        return onlineCompletionMark;
+    }
+    public void setDemandDate(Date demandDate) 
+    {
+        this.demandDate = demandDate;
+    }
+
+    public Date getDemandDate() 
+    {
+        return demandDate;
+    }
+    public void setPlanStartTime(String planStartTime) 
+    {
+        this.planStartTime = planStartTime;
+    }
+
+    public String getPlanStartTime() 
+    {
+        return planStartTime;
+    }
+    public void setPlanEndTime(String planEndTime) 
+    {
+        this.planEndTime = planEndTime;
+    }
+
+    public String getPlanEndTime() 
+    {
+        return planEndTime;
+    }
+    public void setActualStartTime(String actualStartTime) 
+    {
+        this.actualStartTime = actualStartTime;
+    }
+
+    public String getActualStartTime() 
+    {
+        return actualStartTime;
+    }
+    public void setActualEndTime(String actualEndTime) 
+    {
+        this.actualEndTime = actualEndTime;
+    }
+
+    public String getActualEndTime() 
+    {
+        return actualEndTime;
+    }
+    public void setSerialNumber(Long serialNumber) 
+    {
+        this.serialNumber = serialNumber;
+    }
+
+    public Long getSerialNumber() 
+    {
+        return serialNumber;
+    }
+    public void setOrderStatus(String orderStatus) 
+    {
+        this.orderStatus = orderStatus;
+    }
+
+    public String getOrderStatus() 
+    {
+        return orderStatus;
+    }
+    public void setCreateUser(String createUser) 
+    {
+        this.createUser = createUser;
+    }
+
+    public String getCreateUser() 
+    {
+        return createUser;
+    }
+    public void setUpdateUser(String updateUser) 
+    {
+        this.updateUser = updateUser;
+    }
+
+    public String getUpdateUser() 
+    {
+        return updateUser;
+    }
+    public void setRemarks(String remarks) 
+    {
+        this.remarks = remarks;
+    }
+
+    public String getRemarks() 
+    {
+        return remarks;
+    }
+    public void setStreamNumber(String streamNumber) 
+    {
+        this.streamNumber = streamNumber;
+    }
+
+    public String getStreamNumber() 
+    {
+        return streamNumber;
+    }
+    public void setCustom(String custom) 
+    {
+        this.custom = custom;
+    }
+
+    public String getCustom() 
+    {
+        return custom;
+    }
+    public void setMarketAreaCode(String marketAreaCode) 
+    {
+        this.marketAreaCode = marketAreaCode;
+    }
+
+    public String getMarketAreaCode() 
+    {
+        return marketAreaCode;
+    }
+    public void setSoftwareVersionCode(String softwareVersionCode) 
+    {
+        this.softwareVersionCode = softwareVersionCode;
+    }
+
+    public String getSoftwareVersionCode() 
+    {
+        return softwareVersionCode;
+    }
+    public void setProductCompanyCode(String productCompanyCode) 
+    {
+        this.productCompanyCode = productCompanyCode;
+    }
+
+    public String getProductCompanyCode() 
+    {
+        return productCompanyCode;
+    }
+    public void setSpareField1(String spareField1) 
+    {
+        this.spareField1 = spareField1;
+    }
+
+    public String getSpareField1() 
+    {
+        return spareField1;
+    }
+    public void setSpareField2(String spareField2) 
+    {
+        this.spareField2 = spareField2;
+    }
+
+    public String getSpareField2() 
+    {
+        return spareField2;
+    }
+    public void setSpareField3(String spareField3) 
+    {
+        this.spareField3 = spareField3;
+    }
+
+    public String getSpareField3() 
+    {
+        return spareField3;
+    }
+    public void setSpareField4(String spareField4) 
+    {
+        this.spareField4 = spareField4;
+    }
+
+    public String getSpareField4() 
+    {
+        return spareField4;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("workOrderNo", getWorkOrderNo())
+            .append("salesOrderCode", getSalesOrderCode())
+            .append("productCode", getProductCode())
+            .append("productName", getProductName())
+            .append("workshopCode", getWorkshopCode())
+            .append("lineCode", getLineCode())
+            .append("routeCode", getRouteCode())
+            .append("bomCode", getBomCode())
+            .append("recipeCode", getRecipeCode())
+            .append("planQty", getPlanQty())
+            .append("actualQty", getActualQty())
+            .append("badQty", getBadQty())
+            .append("scrapQty", getScrapQty())
+            .append("repairQty", getRepairQty())
+            .append("actualOnlineQty", getActualOnlineQty())
+            .append("onlineCompletionMark", getOnlineCompletionMark())
+            .append("demandDate", getDemandDate())
+            .append("planStartTime", getPlanStartTime())
+            .append("planEndTime", getPlanEndTime())
+            .append("actualStartTime", getActualStartTime())
+            .append("actualEndTime", getActualEndTime())
+            .append("serialNumber", getSerialNumber())
+            .append("orderStatus", getOrderStatus())
+            .append("createTime", getCreateTime())
+            .append("updateTime", getUpdateTime())
+            .append("createUser", getCreateUser())
+            .append("updateUser", getUpdateUser())
+            .append("remarks", getRemarks())
+            .append("streamNumber", getStreamNumber())
+            .append("custom", getCustom())
+            .append("marketAreaCode", getMarketAreaCode())
+            .append("softwareVersionCode", getSoftwareVersionCode())
+            .append("productCompanyCode", getProductCompanyCode())
+            .append("spareField1", getSpareField1())
+            .append("spareField2", getSpareField2())
+            .append("spareField3", getSpareField3())
+            .append("spareField4", getSpareField4())
+            .toString();
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/om/productionOrde/mapper/OmProductionOrdeInfoMapper.java b/jcdm-main/src/main/java/com/jcdm/main/om/productionOrde/mapper/OmProductionOrdeInfoMapper.java
new file mode 100644
index 0000000..fcecab3
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/om/productionOrde/mapper/OmProductionOrdeInfoMapper.java
@@ -0,0 +1,64 @@
+package com.jcdm.main.om.productionOrde.mapper;
+
+import com.jcdm.main.om.productionOrde.domain.OmProductionOrdeInfo;
+
+import java.util.List;
+
+/**
+ * 鐢熶骇宸ュ崟Mapper鎺ュ彛
+ * 
+ * @author ruimin
+ * @date 2023-12-11
+ */
+public interface OmProductionOrdeInfoMapper 
+{
+    /**
+     * 鏌ヨ鐢熶骇宸ュ崟
+     * 
+     * @param id 鐢熶骇宸ュ崟涓婚敭
+     * @return 鐢熶骇宸ュ崟
+     */
+    public OmProductionOrdeInfo selectOmProductionOrdeInfoById(Long id);
+
+    /**
+     * 鏌ヨ鐢熶骇宸ュ崟鍒楄〃
+     * 
+     * @param omProductionOrdeInfo 鐢熶骇宸ュ崟
+     * @return 鐢熶骇宸ュ崟闆嗗悎
+     */
+    public List<OmProductionOrdeInfo> selectOmProductionOrdeInfoList(OmProductionOrdeInfo omProductionOrdeInfo);
+
+    /**
+     * 鏂板鐢熶骇宸ュ崟
+     * 
+     * @param omProductionOrdeInfo 鐢熶骇宸ュ崟
+     * @return 缁撴灉
+     */
+    public int insertOmProductionOrdeInfo(OmProductionOrdeInfo omProductionOrdeInfo);
+
+    /**
+     * 淇敼鐢熶骇宸ュ崟
+     * 
+     * @param omProductionOrdeInfo 鐢熶骇宸ュ崟
+     * @return 缁撴灉
+     */
+    public int updateOmProductionOrdeInfo(OmProductionOrdeInfo omProductionOrdeInfo);
+
+    /**
+     * 鍒犻櫎鐢熶骇宸ュ崟
+     * 
+     * @param id 鐢熶骇宸ュ崟涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteOmProductionOrdeInfoById(Long id);
+
+    /**
+     * 鎵归噺鍒犻櫎鐢熶骇宸ュ崟
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteOmProductionOrdeInfoByIds(Long[] ids);
+
+    public Integer getMaxStreamNumber();
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/om/productionOrde/service/IOmProductionOrdeInfoService.java b/jcdm-main/src/main/java/com/jcdm/main/om/productionOrde/service/IOmProductionOrdeInfoService.java
new file mode 100644
index 0000000..8f5ce40
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/om/productionOrde/service/IOmProductionOrdeInfoService.java
@@ -0,0 +1,65 @@
+package com.jcdm.main.om.productionOrde.service;
+
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.main.om.productionOrde.domain.OmProductionOrdeInfo;
+
+import java.util.List;
+
+/**
+ * 鐢熶骇宸ュ崟Service鎺ュ彛
+ * 
+ * @author ruimin
+ * @date 2023-12-11
+ */
+public interface IOmProductionOrdeInfoService 
+{
+    /**
+     * 鏌ヨ鐢熶骇宸ュ崟
+     * 
+     * @param id 鐢熶骇宸ュ崟涓婚敭
+     * @return 鐢熶骇宸ュ崟
+     */
+    public OmProductionOrdeInfo selectOmProductionOrdeInfoById(Long id);
+
+    /**
+     * 鏌ヨ鐢熶骇宸ュ崟鍒楄〃
+     * 
+     * @param omProductionOrdeInfo 鐢熶骇宸ュ崟
+     * @return 鐢熶骇宸ュ崟闆嗗悎
+     */
+    public List<OmProductionOrdeInfo> selectOmProductionOrdeInfoList(OmProductionOrdeInfo omProductionOrdeInfo);
+
+    /**
+     * 鏂板鐢熶骇宸ュ崟
+     * 
+     * @param omProductionOrdeInfo 鐢熶骇宸ュ崟
+     * @return 缁撴灉
+     */
+    public int insertOmProductionOrdeInfo(OmProductionOrdeInfo omProductionOrdeInfo);
+
+    /**
+     * 淇敼鐢熶骇宸ュ崟
+     * 
+     * @param omProductionOrdeInfo 鐢熶骇宸ュ崟
+     * @return 缁撴灉
+     */
+    public int updateOmProductionOrdeInfo(OmProductionOrdeInfo omProductionOrdeInfo);
+
+    /**
+     * 鎵归噺鍒犻櫎鐢熶骇宸ュ崟
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鐢熶骇宸ュ崟涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteOmProductionOrdeInfoByIds(Long[] ids);
+
+    /**
+     * 鍒犻櫎鐢熶骇宸ュ崟淇℃伅
+     * 
+     * @param id 鐢熶骇宸ュ崟涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteOmProductionOrdeInfoById(Long id);
+
+    AjaxResult upDownMove(OmProductionOrdeInfo omProductionOrdeInfo);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/om/productionOrde/service/impl/OmProductionOrdeInfoServiceImpl.java b/jcdm-main/src/main/java/com/jcdm/main/om/productionOrde/service/impl/OmProductionOrdeInfoServiceImpl.java
new file mode 100644
index 0000000..d7e1aeb
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/om/productionOrde/service/impl/OmProductionOrdeInfoServiceImpl.java
@@ -0,0 +1,137 @@
+package com.jcdm.main.om.productionOrde.service.impl;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.utils.DateUtils;
+import com.jcdm.main.om.productionOrde.domain.OmProductionOrdeInfo;
+import com.jcdm.main.om.productionOrde.mapper.OmProductionOrdeInfoMapper;
+import com.jcdm.main.om.productionOrde.service.IOmProductionOrdeInfoService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * 鐢熶骇宸ュ崟Service涓氬姟灞傚鐞�
+ * 
+ * @author ruimin
+ * @date 2023-12-11
+ */
+@Service
+public class OmProductionOrdeInfoServiceImpl implements IOmProductionOrdeInfoService
+{
+    @Autowired
+    private OmProductionOrdeInfoMapper omProductionOrdeInfoMapper;
+
+    @Autowired
+    private IOmProductionOrdeInfoService omProductionOrdeInfoService;
+
+    /**
+     * 鏌ヨ鐢熶骇宸ュ崟
+     * 
+     * @param id 鐢熶骇宸ュ崟涓婚敭
+     * @return 鐢熶骇宸ュ崟
+     */
+    @Override
+    public OmProductionOrdeInfo selectOmProductionOrdeInfoById(Long id)
+    {
+        return omProductionOrdeInfoMapper.selectOmProductionOrdeInfoById(id);
+    }
+
+    /**
+     * 鏌ヨ鐢熶骇宸ュ崟鍒楄〃
+     * 
+     * @param omProductionOrdeInfo 鐢熶骇宸ュ崟
+     * @return 鐢熶骇宸ュ崟
+     */
+    @Override
+    public List<OmProductionOrdeInfo> selectOmProductionOrdeInfoList(OmProductionOrdeInfo omProductionOrdeInfo)
+    {
+        return omProductionOrdeInfoMapper.selectOmProductionOrdeInfoList(omProductionOrdeInfo);
+    }
+
+    /**
+     * 鏂板鐢熶骇宸ュ崟
+     * 
+     * @param omProductionOrdeInfo 鐢熶骇宸ュ崟
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertOmProductionOrdeInfo(OmProductionOrdeInfo omProductionOrdeInfo)
+    {
+        omProductionOrdeInfo.setCreateTime(DateUtils.getNowDate());
+        Integer streamNumber = omProductionOrdeInfoMapper.getMaxStreamNumber();
+        omProductionOrdeInfo.setStreamNumber(String.valueOf(streamNumber+1));
+        return omProductionOrdeInfoMapper.insertOmProductionOrdeInfo(omProductionOrdeInfo);
+    }
+
+    /**
+     * 淇敼鐢熶骇宸ュ崟
+     * 
+     * @param omProductionOrdeInfo 鐢熶骇宸ュ崟
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateOmProductionOrdeInfo(OmProductionOrdeInfo omProductionOrdeInfo)
+    {
+        omProductionOrdeInfo.setUpdateTime(DateUtils.getNowDate());
+        return omProductionOrdeInfoMapper.updateOmProductionOrdeInfo(omProductionOrdeInfo);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎鐢熶骇宸ュ崟
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鐢熶骇宸ュ崟涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteOmProductionOrdeInfoByIds(Long[] ids)
+    {
+        return omProductionOrdeInfoMapper.deleteOmProductionOrdeInfoByIds(ids);
+    }
+
+    /**
+     * 鍒犻櫎鐢熶骇宸ュ崟淇℃伅
+     * 
+     * @param id 鐢熶骇宸ュ崟涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteOmProductionOrdeInfoById(Long id)
+    {
+        return omProductionOrdeInfoMapper.deleteOmProductionOrdeInfoById(id);
+    }
+
+    @Override
+    public AjaxResult upDownMove(OmProductionOrdeInfo omProductionOrdeInfo) {
+        long currentId = omProductionOrdeInfo.getFrontEndId();
+        List<OmProductionOrdeInfo> omProductionOrdeInfos = omProductionOrdeInfoService.selectOmProductionOrdeInfoList(omProductionOrdeInfo);
+        List<Long> idList = omProductionOrdeInfos.stream()
+                .map(OmProductionOrdeInfo::getId) // 鎻愬彇id灞炴��
+                .collect(Collectors.toList());
+        int index = idList.indexOf(currentId);
+        long moveId = 0L;
+        try {
+            if(omProductionOrdeInfo.getFlag().equals("up")){
+                moveId = idList.get(index - 1);
+            }else {
+                moveId = idList.get(index + 1);
+            }
+        }catch (Exception e){
+            return AjaxResult.error("褰撳墠宸ュ崟涓烘渶鍚庝竴涓垨绗竴涓紝鏃犳硶绉诲姩");
+        }
+        OmProductionOrdeInfo  currentInfo = new OmProductionOrdeInfo();
+        currentInfo.setId(currentId);
+        List<OmProductionOrdeInfo> currentOrdeInfos = omProductionOrdeInfoService.selectOmProductionOrdeInfoList(currentInfo);
+        String currentStreamNumber = currentOrdeInfos.get(0).getStreamNumber();
+        OmProductionOrdeInfo  moveInfo = new OmProductionOrdeInfo();
+        moveInfo.setId(moveId);
+        List<OmProductionOrdeInfo> moveOrdeInfos = omProductionOrdeInfoService.selectOmProductionOrdeInfoList(moveInfo);
+        String moveStreamNumber = moveOrdeInfos.get(0).getStreamNumber();
+        moveOrdeInfos.get(0).setStreamNumber(currentStreamNumber);
+        omProductionOrdeInfoService.updateOmProductionOrdeInfo(moveOrdeInfos.get(0));
+        currentOrdeInfos.get(0).setStreamNumber(moveStreamNumber);
+        omProductionOrdeInfoService.updateOmProductionOrdeInfo(currentOrdeInfos.get(0));
+        return AjaxResult.success("绉诲姩鎴愬姛");
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/om/workReport/controller/OmWorkReportController.java b/jcdm-main/src/main/java/com/jcdm/main/om/workReport/controller/OmWorkReportController.java
new file mode 100644
index 0000000..11f853b
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/om/workReport/controller/OmWorkReportController.java
@@ -0,0 +1,104 @@
+package com.jcdm.main.om.workReport.controller;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.main.om.workReport.domain.OmWorkReport;
+import com.jcdm.main.om.workReport.service.IOmWorkReportService;
+import com.jcdm.common.utils.poi.ExcelUtil;
+import com.jcdm.common.core.page.TableDataInfo;
+
+/**
+ * 鎶ュ伐璁板綍 琛–ontroller
+ * 
+ * @author Yi
+ * @date 2023-12-12
+ */
+@RestController
+@RequestMapping("/om/workReport")
+public class OmWorkReportController extends BaseController
+{
+    @Autowired
+    private IOmWorkReportService omWorkReportService;
+
+    /**
+     * 鏌ヨ鎶ュ伐璁板綍 琛ㄥ垪琛�
+     */
+    @PreAuthorize("@ss.hasPermi('om:workReport:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(OmWorkReport omWorkReport)
+    {
+        startPage();
+        List<OmWorkReport> list = omWorkReportService.selectOmWorkReportList(omWorkReport);
+        return getDataTable(list);
+    }
+
+    /**
+     * 瀵煎嚭鎶ュ伐璁板綍 琛ㄥ垪琛�
+     */
+    @PreAuthorize("@ss.hasPermi('om:workReport:export')")
+    @Log(title = "鎶ュ伐璁板綍 琛�", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, OmWorkReport omWorkReport)
+    {
+        List<OmWorkReport> list = omWorkReportService.selectOmWorkReportList(omWorkReport);
+        ExcelUtil<OmWorkReport> util = new ExcelUtil<OmWorkReport>(OmWorkReport.class);
+        util.exportExcel(response, list, "鎶ュ伐璁板綍 琛ㄦ暟鎹�");
+    }
+
+    /**
+     * 鑾峰彇鎶ュ伐璁板綍 琛ㄨ缁嗕俊鎭�
+     */
+    @PreAuthorize("@ss.hasPermi('om:workReport:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(omWorkReportService.selectOmWorkReportById(id));
+    }
+
+    /**
+     * 鏂板鎶ュ伐璁板綍 琛�
+     */
+    @PreAuthorize("@ss.hasPermi('om:workReport:add')")
+    @Log(title = "鎶ュ伐璁板綍 琛�", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody OmWorkReport omWorkReport)
+    {
+        return toAjax(omWorkReportService.insertOmWorkReport(omWorkReport));
+    }
+
+    /**
+     * 淇敼鎶ュ伐璁板綍 琛�
+     */
+    @PreAuthorize("@ss.hasPermi('om:workReport:edit')")
+    @Log(title = "鎶ュ伐璁板綍 琛�", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody OmWorkReport omWorkReport)
+    {
+        return toAjax(omWorkReportService.updateOmWorkReport(omWorkReport));
+    }
+
+    /**
+     * 鍒犻櫎鎶ュ伐璁板綍 琛�
+     */
+    @PreAuthorize("@ss.hasPermi('om:workReport:remove')")
+    @Log(title = "鎶ュ伐璁板綍 琛�", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(omWorkReportService.deleteOmWorkReportByIds(ids));
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/om/workReport/domain/OmWorkReport.java b/jcdm-main/src/main/java/com/jcdm/main/om/workReport/domain/OmWorkReport.java
new file mode 100644
index 0000000..35d9223
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/om/workReport/domain/OmWorkReport.java
@@ -0,0 +1,223 @@
+package com.jcdm.main.om.workReport.domain;
+
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.core.domain.BaseEntity;
+
+/**
+ * 鎶ュ伐璁板綍 琛ㄥ璞� om_work_report
+ * 
+ * @author Yi
+ * @date 2023-12-12
+ */
+public class OmWorkReport extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 涓婚敭id */
+    private Long id;
+
+    /** 宸ュ崟缂栧彿 */
+    @Excel(name = "宸ュ崟缂栧彿")
+    private String workOrderCode;
+
+    /** SFC鎬绘垚搴忓垪鍙� */
+    @Excel(name = "SFC鎬绘垚搴忓垪鍙�")
+    private String sfcCode;
+
+    /** 浜у搧缂栧彿 */
+    @Excel(name = "浜у搧缂栧彿")
+    private String productCode;
+
+    /** 浜у搧鍚嶇О */
+    @Excel(name = "浜у搧鍚嶇О")
+    private String productName;
+
+    /** 涓婄嚎鏃堕棿 */
+    @Excel(name = "涓婄嚎鏃堕棿")
+    private String upTime;
+
+    /** 涓嬬嚎鏃堕棿 */
+    @Excel(name = "涓嬬嚎鏃堕棿")
+    private String offlineTime;
+
+    /** 鏄惁鍚堟牸 */
+    @Excel(name = "鏄惁鍚堟牸")
+    private String status;
+
+    /** 鍒涘缓鐢ㄦ埛 */
+    @Excel(name = "鍒涘缓鐢ㄦ埛")
+    private String createUser;
+
+    /** 鏇存敼鐢ㄦ埛 */
+    @Excel(name = "鏇存敼鐢ㄦ埛")
+    private String updateUser;
+
+    /** 棰勭暀瀛楁1 */
+    @Excel(name = "棰勭暀瀛楁1")
+    private String spareField1;
+
+    /** 棰勭暀瀛楁2 */
+    @Excel(name = "棰勭暀瀛楁2")
+    private String spareField2;
+
+    /** 棰勭暀瀛楁3 */
+    @Excel(name = "棰勭暀瀛楁3")
+    private String spareField3;
+
+    /** 棰勭暀瀛楁4 */
+    @Excel(name = "棰勭暀瀛楁4")
+    private String spareField4;
+
+    public void setId(Long id) 
+    {
+        this.id = id;
+    }
+
+    public Long getId() 
+    {
+        return id;
+    }
+    public void setWorkOrderCode(String workOrderCode) 
+    {
+        this.workOrderCode = workOrderCode;
+    }
+
+    public String getWorkOrderCode() 
+    {
+        return workOrderCode;
+    }
+    public void setSfcCode(String sfcCode) 
+    {
+        this.sfcCode = sfcCode;
+    }
+
+    public String getSfcCode() 
+    {
+        return sfcCode;
+    }
+    public void setProductCode(String productCode) 
+    {
+        this.productCode = productCode;
+    }
+
+    public String getProductCode() 
+    {
+        return productCode;
+    }
+    public void setProductName(String productName) 
+    {
+        this.productName = productName;
+    }
+
+    public String getProductName() 
+    {
+        return productName;
+    }
+    public void setUpTime(String upTime) 
+    {
+        this.upTime = upTime;
+    }
+
+    public String getUpTime() 
+    {
+        return upTime;
+    }
+    public void setOfflineTime(String offlineTime) 
+    {
+        this.offlineTime = offlineTime;
+    }
+
+    public String getOfflineTime() 
+    {
+        return offlineTime;
+    }
+    public void setStatus(String status) 
+    {
+        this.status = status;
+    }
+
+    public String getStatus() 
+    {
+        return status;
+    }
+    public void setCreateUser(String createUser) 
+    {
+        this.createUser = createUser;
+    }
+
+    public String getCreateUser() 
+    {
+        return createUser;
+    }
+    public void setUpdateUser(String updateUser) 
+    {
+        this.updateUser = updateUser;
+    }
+
+    public String getUpdateUser() 
+    {
+        return updateUser;
+    }
+    public void setSpareField1(String spareField1) 
+    {
+        this.spareField1 = spareField1;
+    }
+
+    public String getSpareField1() 
+    {
+        return spareField1;
+    }
+    public void setSpareField2(String spareField2) 
+    {
+        this.spareField2 = spareField2;
+    }
+
+    public String getSpareField2() 
+    {
+        return spareField2;
+    }
+    public void setSpareField3(String spareField3) 
+    {
+        this.spareField3 = spareField3;
+    }
+
+    public String getSpareField3() 
+    {
+        return spareField3;
+    }
+    public void setSpareField4(String spareField4) 
+    {
+        this.spareField4 = spareField4;
+    }
+
+    public String getSpareField4() 
+    {
+        return spareField4;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("workOrderCode", getWorkOrderCode())
+            .append("sfcCode", getSfcCode())
+            .append("productCode", getProductCode())
+            .append("productName", getProductName())
+            .append("upTime", getUpTime())
+            .append("offlineTime", getOfflineTime())
+            .append("status", getStatus())
+            .append("createUser", getCreateUser())
+            .append("createTime", getCreateTime())
+            .append("updateUser", getUpdateUser())
+            .append("updateTime", getUpdateTime())
+            .append("remark", getRemark())
+            .append("spareField1", getSpareField1())
+            .append("spareField2", getSpareField2())
+            .append("spareField3", getSpareField3())
+            .append("spareField4", getSpareField4())
+            .toString();
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/om/workReport/mapper/OmWorkReportMapper.java b/jcdm-main/src/main/java/com/jcdm/main/om/workReport/mapper/OmWorkReportMapper.java
new file mode 100644
index 0000000..210b189
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/om/workReport/mapper/OmWorkReportMapper.java
@@ -0,0 +1,61 @@
+package com.jcdm.main.om.workReport.mapper;
+
+import java.util.List;
+import com.jcdm.main.om.workReport.domain.OmWorkReport;
+
+/**
+ * 鎶ュ伐璁板綍 琛∕apper鎺ュ彛
+ * 
+ * @author Yi
+ * @date 2023-12-12
+ */
+public interface OmWorkReportMapper 
+{
+    /**
+     * 鏌ヨ鎶ュ伐璁板綍 琛�
+     * 
+     * @param id 鎶ュ伐璁板綍 琛ㄤ富閿�
+     * @return 鎶ュ伐璁板綍 琛�
+     */
+    public OmWorkReport selectOmWorkReportById(Long id);
+
+    /**
+     * 鏌ヨ鎶ュ伐璁板綍 琛ㄥ垪琛�
+     * 
+     * @param omWorkReport 鎶ュ伐璁板綍 琛�
+     * @return 鎶ュ伐璁板綍 琛ㄩ泦鍚�
+     */
+    public List<OmWorkReport> selectOmWorkReportList(OmWorkReport omWorkReport);
+
+    /**
+     * 鏂板鎶ュ伐璁板綍 琛�
+     * 
+     * @param omWorkReport 鎶ュ伐璁板綍 琛�
+     * @return 缁撴灉
+     */
+    public int insertOmWorkReport(OmWorkReport omWorkReport);
+
+    /**
+     * 淇敼鎶ュ伐璁板綍 琛�
+     * 
+     * @param omWorkReport 鎶ュ伐璁板綍 琛�
+     * @return 缁撴灉
+     */
+    public int updateOmWorkReport(OmWorkReport omWorkReport);
+
+    /**
+     * 鍒犻櫎鎶ュ伐璁板綍 琛�
+     * 
+     * @param id 鎶ュ伐璁板綍 琛ㄤ富閿�
+     * @return 缁撴灉
+     */
+    public int deleteOmWorkReportById(Long id);
+
+    /**
+     * 鎵归噺鍒犻櫎鎶ュ伐璁板綍 琛�
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteOmWorkReportByIds(Long[] ids);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/om/workReport/service/IOmWorkReportService.java b/jcdm-main/src/main/java/com/jcdm/main/om/workReport/service/IOmWorkReportService.java
new file mode 100644
index 0000000..3b0e18a
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/om/workReport/service/IOmWorkReportService.java
@@ -0,0 +1,61 @@
+package com.jcdm.main.om.workReport.service;
+
+import java.util.List;
+import com.jcdm.main.om.workReport.domain.OmWorkReport;
+
+/**
+ * 鎶ュ伐璁板綍 琛⊿ervice鎺ュ彛
+ * 
+ * @author Yi
+ * @date 2023-12-12
+ */
+public interface IOmWorkReportService 
+{
+    /**
+     * 鏌ヨ鎶ュ伐璁板綍 琛�
+     * 
+     * @param id 鎶ュ伐璁板綍 琛ㄤ富閿�
+     * @return 鎶ュ伐璁板綍 琛�
+     */
+    public OmWorkReport selectOmWorkReportById(Long id);
+
+    /**
+     * 鏌ヨ鎶ュ伐璁板綍 琛ㄥ垪琛�
+     * 
+     * @param omWorkReport 鎶ュ伐璁板綍 琛�
+     * @return 鎶ュ伐璁板綍 琛ㄩ泦鍚�
+     */
+    public List<OmWorkReport> selectOmWorkReportList(OmWorkReport omWorkReport);
+
+    /**
+     * 鏂板鎶ュ伐璁板綍 琛�
+     * 
+     * @param omWorkReport 鎶ュ伐璁板綍 琛�
+     * @return 缁撴灉
+     */
+    public int insertOmWorkReport(OmWorkReport omWorkReport);
+
+    /**
+     * 淇敼鎶ュ伐璁板綍 琛�
+     * 
+     * @param omWorkReport 鎶ュ伐璁板綍 琛�
+     * @return 缁撴灉
+     */
+    public int updateOmWorkReport(OmWorkReport omWorkReport);
+
+    /**
+     * 鎵归噺鍒犻櫎鎶ュ伐璁板綍 琛�
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鎶ュ伐璁板綍 琛ㄤ富閿泦鍚�
+     * @return 缁撴灉
+     */
+    public int deleteOmWorkReportByIds(Long[] ids);
+
+    /**
+     * 鍒犻櫎鎶ュ伐璁板綍 琛ㄤ俊鎭�
+     * 
+     * @param id 鎶ュ伐璁板綍 琛ㄤ富閿�
+     * @return 缁撴灉
+     */
+    public int deleteOmWorkReportById(Long id);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/om/workReport/service/impl/OmWorkReportServiceImpl.java b/jcdm-main/src/main/java/com/jcdm/main/om/workReport/service/impl/OmWorkReportServiceImpl.java
new file mode 100644
index 0000000..8155095
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/om/workReport/service/impl/OmWorkReportServiceImpl.java
@@ -0,0 +1,96 @@
+package com.jcdm.main.om.workReport.service.impl;
+
+import java.util.List;
+import com.jcdm.common.utils.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.jcdm.main.om.workReport.mapper.OmWorkReportMapper;
+import com.jcdm.main.om.workReport.domain.OmWorkReport;
+import com.jcdm.main.om.workReport.service.IOmWorkReportService;
+
+/**
+ * 鎶ュ伐璁板綍 琛⊿ervice涓氬姟灞傚鐞�
+ * 
+ * @author Yi
+ * @date 2023-12-12
+ */
+@Service
+public class OmWorkReportServiceImpl implements IOmWorkReportService 
+{
+    @Autowired
+    private OmWorkReportMapper omWorkReportMapper;
+
+    /**
+     * 鏌ヨ鎶ュ伐璁板綍 琛�
+     * 
+     * @param id 鎶ュ伐璁板綍 琛ㄤ富閿�
+     * @return 鎶ュ伐璁板綍 琛�
+     */
+    @Override
+    public OmWorkReport selectOmWorkReportById(Long id)
+    {
+        return omWorkReportMapper.selectOmWorkReportById(id);
+    }
+
+    /**
+     * 鏌ヨ鎶ュ伐璁板綍 琛ㄥ垪琛�
+     * 
+     * @param omWorkReport 鎶ュ伐璁板綍 琛�
+     * @return 鎶ュ伐璁板綍 琛�
+     */
+    @Override
+    public List<OmWorkReport> selectOmWorkReportList(OmWorkReport omWorkReport)
+    {
+        return omWorkReportMapper.selectOmWorkReportList(omWorkReport);
+    }
+
+    /**
+     * 鏂板鎶ュ伐璁板綍 琛�
+     * 
+     * @param omWorkReport 鎶ュ伐璁板綍 琛�
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertOmWorkReport(OmWorkReport omWorkReport)
+    {
+        omWorkReport.setCreateTime(DateUtils.getNowDate());
+        return omWorkReportMapper.insertOmWorkReport(omWorkReport);
+    }
+
+    /**
+     * 淇敼鎶ュ伐璁板綍 琛�
+     * 
+     * @param omWorkReport 鎶ュ伐璁板綍 琛�
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateOmWorkReport(OmWorkReport omWorkReport)
+    {
+        omWorkReport.setUpdateTime(DateUtils.getNowDate());
+        return omWorkReportMapper.updateOmWorkReport(omWorkReport);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎鎶ュ伐璁板綍 琛�
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鎶ュ伐璁板綍 琛ㄤ富閿�
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteOmWorkReportByIds(Long[] ids)
+    {
+        return omWorkReportMapper.deleteOmWorkReportByIds(ids);
+    }
+
+    /**
+     * 鍒犻櫎鎶ュ伐璁板綍 琛ㄤ俊鎭�
+     * 
+     * @param id 鎶ュ伐璁板綍 琛ㄤ富閿�
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteOmWorkReportById(Long id)
+    {
+        return omWorkReportMapper.deleteOmWorkReportById(id);
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/rm/repairData/controller/RmRepairDataController.java b/jcdm-main/src/main/java/com/jcdm/main/rm/repairData/controller/RmRepairDataController.java
new file mode 100644
index 0000000..ad8af11
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/rm/repairData/controller/RmRepairDataController.java
@@ -0,0 +1,104 @@
+package com.jcdm.main.rm.repairData.controller;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.main.rm.repairData.domain.RmRepairData;
+import com.jcdm.main.rm.repairData.service.IRmRepairDataService;
+import com.jcdm.common.utils.poi.ExcelUtil;
+import com.jcdm.common.core.page.TableDataInfo;
+
+/**
+ * 杩斾慨鏁版嵁Controller
+ * 
+ * @author Yi
+ * @date 2023-12-22
+ */
+@RestController
+@RequestMapping("/rm/repairData")
+public class RmRepairDataController extends BaseController
+{
+    @Autowired
+    private IRmRepairDataService rmRepairDataService;
+
+    /**
+     * 鏌ヨ杩斾慨鏁版嵁鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('rm:repairData:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(RmRepairData rmRepairData)
+    {
+        startPage();
+        List<RmRepairData> list = rmRepairDataService.selectRmRepairDataList(rmRepairData);
+        return getDataTable(list);
+    }
+
+    /**
+     * 瀵煎嚭杩斾慨鏁版嵁鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('rm:repairData:export')")
+    @Log(title = "杩斾慨鏁版嵁", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, RmRepairData rmRepairData)
+    {
+        List<RmRepairData> list = rmRepairDataService.selectRmRepairDataList(rmRepairData);
+        ExcelUtil<RmRepairData> util = new ExcelUtil<RmRepairData>(RmRepairData.class);
+        util.exportExcel(response, list, "杩斾慨鏁版嵁鏁版嵁");
+    }
+
+    /**
+     * 鑾峰彇杩斾慨鏁版嵁璇︾粏淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('rm:repairData:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(rmRepairDataService.selectRmRepairDataById(id));
+    }
+
+    /**
+     * 鏂板杩斾慨鏁版嵁
+     */
+    @PreAuthorize("@ss.hasPermi('rm:repairData:add')")
+    @Log(title = "杩斾慨鏁版嵁", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody RmRepairData rmRepairData)
+    {
+        return toAjax(rmRepairDataService.insertRmRepairData(rmRepairData));
+    }
+
+    /**
+     * 淇敼杩斾慨鏁版嵁
+     */
+    @PreAuthorize("@ss.hasPermi('rm:repairData:edit')")
+    @Log(title = "杩斾慨鏁版嵁", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody RmRepairData rmRepairData)
+    {
+        return toAjax(rmRepairDataService.updateRmRepairData(rmRepairData));
+    }
+
+    /**
+     * 鍒犻櫎杩斾慨鏁版嵁
+     */
+    @PreAuthorize("@ss.hasPermi('rm:repairData:remove')")
+    @Log(title = "杩斾慨鏁版嵁", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(rmRepairDataService.deleteRmRepairDataByIds(ids));
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/rm/repairData/domain/RmRepairData.java b/jcdm-main/src/main/java/com/jcdm/main/rm/repairData/domain/RmRepairData.java
new file mode 100644
index 0000000..b242b1b
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/rm/repairData/domain/RmRepairData.java
@@ -0,0 +1,233 @@
+package com.jcdm.main.rm.repairData.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.core.domain.BaseEntity;
+
+/**
+ * 杩斾慨鏁版嵁瀵硅薄 rm_repair_data
+ * 
+ * @author Yi
+ * @date 2023-12-22
+ */
+public class RmRepairData extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 涓婚敭id */
+    private Long id;
+
+    /** 鎬绘垚缂栫爜 */
+    @Excel(name = "鎬绘垚缂栫爜")
+    private String snCode;
+
+    /** 绠变綋缂栫爜 */
+    @Excel(name = "绠变綋缂栫爜")
+    private String boxCode;
+
+    /** 宸ュ簭缂栫爜 */
+    @Excel(name = "宸ュ簭缂栫爜")
+    private String processesCode;
+
+    /** 鎷х揣娆℃暟 */
+    @Excel(name = "鎷х揣娆℃暟")
+    private String tightenFrequency;
+
+    /** 鎷х揣棰楁暟 */
+    @Excel(name = "鎷х揣棰楁暟")
+    private String tightenPiecesNumber;
+
+    /** 鎵姏 */
+    @Excel(name = "鎵姏")
+    private String torqueForce;
+
+    /** 瑙掑害 */
+    @Excel(name = "瑙掑害")
+    private String angle;
+
+    /** 缁撴灉 */
+    @Excel(name = "缁撴灉")
+    private String result;
+
+    /** 鍒涘缓鐢ㄦ埛 */
+    @Excel(name = "鍒涘缓鐢ㄦ埛")
+    private String createUser;
+
+    /** 鏇存柊鐢ㄦ埛 */
+    @Excel(name = "鏇存柊鐢ㄦ埛")
+    private String updateUser;
+
+    /** 澶囨敞 */
+    @Excel(name = "澶囨敞")
+    private String remarks;
+
+    /** 棰勭暀瀛楁1 */
+    @Excel(name = "棰勭暀瀛楁1")
+    private String spareField1;
+
+    /** 棰勭暀瀛楁2 */
+    @Excel(name = "棰勭暀瀛楁2")
+    private String spareField2;
+    @Excel(name = "宸ヤ綅")
+    private String station;
+
+    public void setId(Long id) 
+    {
+        this.id = id;
+    }
+
+    public Long getId() 
+    {
+        return id;
+    }
+    public void setSnCode(String snCode) 
+    {
+        this.snCode = snCode;
+    }
+
+    public String getSnCode() 
+    {
+        return snCode;
+    }
+    public void setBoxCode(String boxCode) 
+    {
+        this.boxCode = boxCode;
+    }
+
+    public String getBoxCode() 
+    {
+        return boxCode;
+    }
+    public void setProcessesCode(String processesCode) 
+    {
+        this.processesCode = processesCode;
+    }
+
+    public String getProcessesCode() 
+    {
+        return processesCode;
+    }
+    public void setTightenFrequency(String tightenFrequency) 
+    {
+        this.tightenFrequency = tightenFrequency;
+    }
+
+    public String getTightenFrequency() 
+    {
+        return tightenFrequency;
+    }
+    public void setTightenPiecesNumber(String tightenPiecesNumber) 
+    {
+        this.tightenPiecesNumber = tightenPiecesNumber;
+    }
+
+    public String getTightenPiecesNumber() 
+    {
+        return tightenPiecesNumber;
+    }
+    public void setTorqueForce(String torqueForce) 
+    {
+        this.torqueForce = torqueForce;
+    }
+
+    public String getTorqueForce() 
+    {
+        return torqueForce;
+    }
+    public void setAngle(String angle) 
+    {
+        this.angle = angle;
+    }
+
+    public String getAngle() 
+    {
+        return angle;
+    }
+
+    public void setStation(String station)
+    {
+        this.station = station;
+    }
+
+    public String getStation()
+    {
+        return station;
+    }
+    public void setResult(String result) 
+    {
+        this.result = result;
+    }
+
+    public String getResult() 
+    {
+        return result;
+    }
+    public void setCreateUser(String createUser) 
+    {
+        this.createUser = createUser;
+    }
+
+    public String getCreateUser() 
+    {
+        return createUser;
+    }
+    public void setUpdateUser(String updateUser) 
+    {
+        this.updateUser = updateUser;
+    }
+
+    public String getUpdateUser() 
+    {
+        return updateUser;
+    }
+    public void setRemarks(String remarks) 
+    {
+        this.remarks = remarks;
+    }
+
+    public String getRemarks() 
+    {
+        return remarks;
+    }
+    public void setSpareField1(String spareField1) 
+    {
+        this.spareField1 = spareField1;
+    }
+
+    public String getSpareField1() 
+    {
+        return spareField1;
+    }
+    public void setSpareField2(String spareField2) 
+    {
+        this.spareField2 = spareField2;
+    }
+
+    public String getSpareField2() 
+    {
+        return spareField2;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("snCode", getSnCode())
+            .append("boxCode", getBoxCode())
+            .append("processesCode", getProcessesCode())
+            .append("tightenFrequency", getTightenFrequency())
+            .append("tightenPiecesNumber", getTightenPiecesNumber())
+            .append("torqueForce", getTorqueForce())
+            .append("angle", getAngle())
+            .append("result", getResult())
+            .append("createUser", getCreateUser())
+            .append("createTime", getCreateTime())
+            .append("updateTime", getUpdateTime())
+            .append("updateUser", getUpdateUser())
+            .append("remarks", getRemarks())
+            .append("spareField1", getSpareField1())
+            .append("spareField2", getSpareField2())
+            .toString();
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/rm/repairData/mapper/RmRepairDataMapper.java b/jcdm-main/src/main/java/com/jcdm/main/rm/repairData/mapper/RmRepairDataMapper.java
new file mode 100644
index 0000000..d288f89
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/rm/repairData/mapper/RmRepairDataMapper.java
@@ -0,0 +1,61 @@
+package com.jcdm.main.rm.repairData.mapper;
+
+import java.util.List;
+import com.jcdm.main.rm.repairData.domain.RmRepairData;
+
+/**
+ * 杩斾慨鏁版嵁Mapper鎺ュ彛
+ * 
+ * @author Yi
+ * @date 2023-12-22
+ */
+public interface RmRepairDataMapper 
+{
+    /**
+     * 鏌ヨ杩斾慨鏁版嵁
+     * 
+     * @param id 杩斾慨鏁版嵁涓婚敭
+     * @return 杩斾慨鏁版嵁
+     */
+    public RmRepairData selectRmRepairDataById(Long id);
+
+    /**
+     * 鏌ヨ杩斾慨鏁版嵁鍒楄〃
+     * 
+     * @param rmRepairData 杩斾慨鏁版嵁
+     * @return 杩斾慨鏁版嵁闆嗗悎
+     */
+    public List<RmRepairData> selectRmRepairDataList(RmRepairData rmRepairData);
+
+    /**
+     * 鏂板杩斾慨鏁版嵁
+     * 
+     * @param rmRepairData 杩斾慨鏁版嵁
+     * @return 缁撴灉
+     */
+    public int insertRmRepairData(RmRepairData rmRepairData);
+
+    /**
+     * 淇敼杩斾慨鏁版嵁
+     * 
+     * @param rmRepairData 杩斾慨鏁版嵁
+     * @return 缁撴灉
+     */
+    public int updateRmRepairData(RmRepairData rmRepairData);
+
+    /**
+     * 鍒犻櫎杩斾慨鏁版嵁
+     * 
+     * @param id 杩斾慨鏁版嵁涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteRmRepairDataById(Long id);
+
+    /**
+     * 鎵归噺鍒犻櫎杩斾慨鏁版嵁
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteRmRepairDataByIds(Long[] ids);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/rm/repairData/service/IRmRepairDataService.java b/jcdm-main/src/main/java/com/jcdm/main/rm/repairData/service/IRmRepairDataService.java
new file mode 100644
index 0000000..c758711
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/rm/repairData/service/IRmRepairDataService.java
@@ -0,0 +1,61 @@
+package com.jcdm.main.rm.repairData.service;
+
+import java.util.List;
+import com.jcdm.main.rm.repairData.domain.RmRepairData;
+
+/**
+ * 杩斾慨鏁版嵁Service鎺ュ彛
+ * 
+ * @author Yi
+ * @date 2023-12-22
+ */
+public interface IRmRepairDataService 
+{
+    /**
+     * 鏌ヨ杩斾慨鏁版嵁
+     * 
+     * @param id 杩斾慨鏁版嵁涓婚敭
+     * @return 杩斾慨鏁版嵁
+     */
+    public RmRepairData selectRmRepairDataById(Long id);
+
+    /**
+     * 鏌ヨ杩斾慨鏁版嵁鍒楄〃
+     * 
+     * @param rmRepairData 杩斾慨鏁版嵁
+     * @return 杩斾慨鏁版嵁闆嗗悎
+     */
+    public List<RmRepairData> selectRmRepairDataList(RmRepairData rmRepairData);
+
+    /**
+     * 鏂板杩斾慨鏁版嵁
+     * 
+     * @param rmRepairData 杩斾慨鏁版嵁
+     * @return 缁撴灉
+     */
+    public int insertRmRepairData(RmRepairData rmRepairData);
+
+    /**
+     * 淇敼杩斾慨鏁版嵁
+     * 
+     * @param rmRepairData 杩斾慨鏁版嵁
+     * @return 缁撴灉
+     */
+    public int updateRmRepairData(RmRepairData rmRepairData);
+
+    /**
+     * 鎵归噺鍒犻櫎杩斾慨鏁版嵁
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑杩斾慨鏁版嵁涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteRmRepairDataByIds(Long[] ids);
+
+    /**
+     * 鍒犻櫎杩斾慨鏁版嵁淇℃伅
+     * 
+     * @param id 杩斾慨鏁版嵁涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteRmRepairDataById(Long id);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/rm/repairData/service/impl/RmRepairDataServiceImpl.java b/jcdm-main/src/main/java/com/jcdm/main/rm/repairData/service/impl/RmRepairDataServiceImpl.java
new file mode 100644
index 0000000..92f32d7
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/rm/repairData/service/impl/RmRepairDataServiceImpl.java
@@ -0,0 +1,96 @@
+package com.jcdm.main.rm.repairData.service.impl;
+
+import java.util.List;
+import com.jcdm.common.utils.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.jcdm.main.rm.repairData.mapper.RmRepairDataMapper;
+import com.jcdm.main.rm.repairData.domain.RmRepairData;
+import com.jcdm.main.rm.repairData.service.IRmRepairDataService;
+
+/**
+ * 杩斾慨鏁版嵁Service涓氬姟灞傚鐞�
+ * 
+ * @author Yi
+ * @date 2023-12-22
+ */
+@Service
+public class RmRepairDataServiceImpl implements IRmRepairDataService 
+{
+    @Autowired
+    private RmRepairDataMapper rmRepairDataMapper;
+
+    /**
+     * 鏌ヨ杩斾慨鏁版嵁
+     * 
+     * @param id 杩斾慨鏁版嵁涓婚敭
+     * @return 杩斾慨鏁版嵁
+     */
+    @Override
+    public RmRepairData selectRmRepairDataById(Long id)
+    {
+        return rmRepairDataMapper.selectRmRepairDataById(id);
+    }
+
+    /**
+     * 鏌ヨ杩斾慨鏁版嵁鍒楄〃
+     * 
+     * @param rmRepairData 杩斾慨鏁版嵁
+     * @return 杩斾慨鏁版嵁
+     */
+    @Override
+    public List<RmRepairData> selectRmRepairDataList(RmRepairData rmRepairData)
+    {
+        return rmRepairDataMapper.selectRmRepairDataList(rmRepairData);
+    }
+
+    /**
+     * 鏂板杩斾慨鏁版嵁
+     * 
+     * @param rmRepairData 杩斾慨鏁版嵁
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertRmRepairData(RmRepairData rmRepairData)
+    {
+        rmRepairData.setCreateTime(DateUtils.getNowDate());
+        return rmRepairDataMapper.insertRmRepairData(rmRepairData);
+    }
+
+    /**
+     * 淇敼杩斾慨鏁版嵁
+     * 
+     * @param rmRepairData 杩斾慨鏁版嵁
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateRmRepairData(RmRepairData rmRepairData)
+    {
+        rmRepairData.setUpdateTime(DateUtils.getNowDate());
+        return rmRepairDataMapper.updateRmRepairData(rmRepairData);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎杩斾慨鏁版嵁
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑杩斾慨鏁版嵁涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteRmRepairDataByIds(Long[] ids)
+    {
+        return rmRepairDataMapper.deleteRmRepairDataByIds(ids);
+    }
+
+    /**
+     * 鍒犻櫎杩斾慨鏁版嵁淇℃伅
+     * 
+     * @param id 杩斾慨鏁版嵁涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteRmRepairDataById(Long id)
+    {
+        return rmRepairDataMapper.deleteRmRepairDataById(id);
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/rm/repairRecord/controller/RmRepairRecordController.java b/jcdm-main/src/main/java/com/jcdm/main/rm/repairRecord/controller/RmRepairRecordController.java
new file mode 100644
index 0000000..b4ed99a
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/rm/repairRecord/controller/RmRepairRecordController.java
@@ -0,0 +1,104 @@
+package com.jcdm.main.rm.repairRecord.controller;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.main.rm.repairRecord.domain.RmRepairRecord;
+import com.jcdm.main.rm.repairRecord.service.IRmRepairRecordService;
+import com.jcdm.common.utils.poi.ExcelUtil;
+import com.jcdm.common.core.page.TableDataInfo;
+
+/**
+ * 杩斾慨璁板綍Controller
+ * 
+ * @author Yi
+ * @date 2023-12-22
+ */
+@RestController
+@RequestMapping("/rm/repairRecord")
+public class RmRepairRecordController extends BaseController
+{
+    @Autowired
+    private IRmRepairRecordService rmRepairRecordService;
+
+    /**
+     * 鏌ヨ杩斾慨璁板綍鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('rm:repairRecord:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(RmRepairRecord rmRepairRecord)
+    {
+        startPage();
+        List<RmRepairRecord> list = rmRepairRecordService.selectRmRepairRecordList(rmRepairRecord);
+        return getDataTable(list);
+    }
+
+    /**
+     * 瀵煎嚭杩斾慨璁板綍鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('rm:repairRecord:export')")
+    @Log(title = "杩斾慨璁板綍", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, RmRepairRecord rmRepairRecord)
+    {
+        List<RmRepairRecord> list = rmRepairRecordService.selectRmRepairRecordList(rmRepairRecord);
+        ExcelUtil<RmRepairRecord> util = new ExcelUtil<RmRepairRecord>(RmRepairRecord.class);
+        util.exportExcel(response, list, "杩斾慨璁板綍鏁版嵁");
+    }
+
+    /**
+     * 鑾峰彇杩斾慨璁板綍璇︾粏淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('rm:repairRecord:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(rmRepairRecordService.selectRmRepairRecordById(id));
+    }
+
+    /**
+     * 鏂板杩斾慨璁板綍
+     */
+    @PreAuthorize("@ss.hasPermi('rm:repairRecord:add')")
+    @Log(title = "杩斾慨璁板綍", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody RmRepairRecord rmRepairRecord)
+    {
+        return toAjax(rmRepairRecordService.insertRmRepairRecord(rmRepairRecord));
+    }
+
+    /**
+     * 淇敼杩斾慨璁板綍
+     */
+    @PreAuthorize("@ss.hasPermi('rm:repairRecord:edit')")
+    @Log(title = "杩斾慨璁板綍", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody RmRepairRecord rmRepairRecord)
+    {
+        return toAjax(rmRepairRecordService.updateRmRepairRecord(rmRepairRecord));
+    }
+
+    /**
+     * 鍒犻櫎杩斾慨璁板綍
+     */
+    @PreAuthorize("@ss.hasPermi('rm:repairRecord:remove')")
+    @Log(title = "杩斾慨璁板綍", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(rmRepairRecordService.deleteRmRepairRecordByIds(ids));
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/rm/repairRecord/domain/RmRepairRecord.java b/jcdm-main/src/main/java/com/jcdm/main/rm/repairRecord/domain/RmRepairRecord.java
new file mode 100644
index 0000000..92b0ad0
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/rm/repairRecord/domain/RmRepairRecord.java
@@ -0,0 +1,207 @@
+package com.jcdm.main.rm.repairRecord.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.core.domain.BaseEntity;
+
+/**
+ * 杩斾慨璁板綍瀵硅薄 rm_repair_record
+ * 
+ * @author Yi
+ * @date 2023-12-22
+ */
+public class RmRepairRecord extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 涓婚敭id */
+    private Long id;
+
+    /** 鎬绘垚缂栫爜 */
+    @Excel(name = "鎬绘垚缂栫爜")
+    private String snCode;
+
+    /** 杩斾慨鏍囪瘑 */
+    @Excel(name = "杩斾慨鏍囪瘑")
+    private String repairIdentification;
+
+    /** 绠变綋缂栫爜 */
+    @Excel(name = "绠变綋缂栫爜")
+    private String boxCode;
+
+    /** 宸ュ簭缂栫爜 */
+    @Excel(name = "宸ュ簭缂栫爜")
+    private String processesCode;
+
+    /** 鍘熺粨鏋� */
+    @Excel(name = "鍘熺粨鏋�")
+    private String originalResult;
+
+    /** 鍒涘缓鐢ㄦ埛 */
+    @Excel(name = "鍒涘缓鐢ㄦ埛")
+    private String createUser;
+
+    /** 鏇存柊鐢ㄦ埛 */
+    @Excel(name = "鏇存柊鐢ㄦ埛")
+    private String updateUser;
+
+    /** 杩斾慨缁撴灉 */
+    @Excel(name = "杩斾慨缁撴灉")
+    private String repairResults;
+
+    /** 鐘舵�� */
+    @Excel(name = "鐘舵��")
+    private String status;
+
+    /** 澶囨敞 */
+    @Excel(name = "澶囨敞")
+    private String remarks;
+
+    /** 棰勭暀瀛楁1 */
+    @Excel(name = "棰勭暀瀛楁1")
+    private String spareField1;
+
+    /** 棰勭暀瀛楁2 */
+    @Excel(name = "棰勭暀瀛楁2")
+    private String spareField2;
+
+    public void setId(Long id) 
+    {
+        this.id = id;
+    }
+
+    public Long getId() 
+    {
+        return id;
+    }
+    public void setSnCode(String snCode) 
+    {
+        this.snCode = snCode;
+    }
+
+    public String getSnCode() 
+    {
+        return snCode;
+    }
+    public void setRepairIdentification(String repairIdentification) 
+    {
+        this.repairIdentification = repairIdentification;
+    }
+
+    public String getRepairIdentification() 
+    {
+        return repairIdentification;
+    }
+    public void setBoxCode(String boxCode) 
+    {
+        this.boxCode = boxCode;
+    }
+
+    public String getBoxCode() 
+    {
+        return boxCode;
+    }
+    public void setProcessesCode(String processesCode) 
+    {
+        this.processesCode = processesCode;
+    }
+
+    public String getProcessesCode() 
+    {
+        return processesCode;
+    }
+    public void setOriginalResult(String originalResult) 
+    {
+        this.originalResult = originalResult;
+    }
+
+    public String getOriginalResult() 
+    {
+        return originalResult;
+    }
+    public void setCreateUser(String createUser) 
+    {
+        this.createUser = createUser;
+    }
+
+    public String getCreateUser() 
+    {
+        return createUser;
+    }
+    public void setUpdateUser(String updateUser) 
+    {
+        this.updateUser = updateUser;
+    }
+
+    public String getUpdateUser() 
+    {
+        return updateUser;
+    }
+    public void setRepairResults(String repairResults) 
+    {
+        this.repairResults = repairResults;
+    }
+
+    public String getRepairResults() 
+    {
+        return repairResults;
+    }
+    public void setStatus(String status) 
+    {
+        this.status = status;
+    }
+
+    public String getStatus() 
+    {
+        return status;
+    }
+    public void setRemarks(String remarks) 
+    {
+        this.remarks = remarks;
+    }
+
+    public String getRemarks() 
+    {
+        return remarks;
+    }
+    public void setSpareField1(String spareField1) 
+    {
+        this.spareField1 = spareField1;
+    }
+
+    public String getSpareField1() 
+    {
+        return spareField1;
+    }
+    public void setSpareField2(String spareField2) 
+    {
+        this.spareField2 = spareField2;
+    }
+
+    public String getSpareField2() 
+    {
+        return spareField2;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("snCode", getSnCode())
+            .append("repairIdentification", getRepairIdentification())
+            .append("boxCode", getBoxCode())
+            .append("processesCode", getProcessesCode())
+            .append("originalResult", getOriginalResult())
+            .append("createUser", getCreateUser())
+            .append("createTime", getCreateTime())
+            .append("updateTime", getUpdateTime())
+            .append("updateUser", getUpdateUser())
+            .append("repairResults", getRepairResults())
+            .append("status", getStatus())
+            .append("remarks", getRemarks())
+            .append("spareField1", getSpareField1())
+            .append("spareField2", getSpareField2())
+            .toString();
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/rm/repairRecord/mapper/RmRepairRecordMapper.java b/jcdm-main/src/main/java/com/jcdm/main/rm/repairRecord/mapper/RmRepairRecordMapper.java
new file mode 100644
index 0000000..69e6019
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/rm/repairRecord/mapper/RmRepairRecordMapper.java
@@ -0,0 +1,61 @@
+package com.jcdm.main.rm.repairRecord.mapper;
+
+import java.util.List;
+import com.jcdm.main.rm.repairRecord.domain.RmRepairRecord;
+
+/**
+ * 杩斾慨璁板綍Mapper鎺ュ彛
+ * 
+ * @author Yi
+ * @date 2023-12-22
+ */
+public interface RmRepairRecordMapper 
+{
+    /**
+     * 鏌ヨ杩斾慨璁板綍
+     * 
+     * @param id 杩斾慨璁板綍涓婚敭
+     * @return 杩斾慨璁板綍
+     */
+    public RmRepairRecord selectRmRepairRecordById(Long id);
+
+    /**
+     * 鏌ヨ杩斾慨璁板綍鍒楄〃
+     * 
+     * @param rmRepairRecord 杩斾慨璁板綍
+     * @return 杩斾慨璁板綍闆嗗悎
+     */
+    public List<RmRepairRecord> selectRmRepairRecordList(RmRepairRecord rmRepairRecord);
+
+    /**
+     * 鏂板杩斾慨璁板綍
+     * 
+     * @param rmRepairRecord 杩斾慨璁板綍
+     * @return 缁撴灉
+     */
+    public int insertRmRepairRecord(RmRepairRecord rmRepairRecord);
+
+    /**
+     * 淇敼杩斾慨璁板綍
+     * 
+     * @param rmRepairRecord 杩斾慨璁板綍
+     * @return 缁撴灉
+     */
+    public int updateRmRepairRecord(RmRepairRecord rmRepairRecord);
+
+    /**
+     * 鍒犻櫎杩斾慨璁板綍
+     * 
+     * @param id 杩斾慨璁板綍涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteRmRepairRecordById(Long id);
+
+    /**
+     * 鎵归噺鍒犻櫎杩斾慨璁板綍
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteRmRepairRecordByIds(Long[] ids);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/rm/repairRecord/service/IRmRepairRecordService.java b/jcdm-main/src/main/java/com/jcdm/main/rm/repairRecord/service/IRmRepairRecordService.java
new file mode 100644
index 0000000..ef0b797
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/rm/repairRecord/service/IRmRepairRecordService.java
@@ -0,0 +1,61 @@
+package com.jcdm.main.rm.repairRecord.service;
+
+import java.util.List;
+import com.jcdm.main.rm.repairRecord.domain.RmRepairRecord;
+
+/**
+ * 杩斾慨璁板綍Service鎺ュ彛
+ * 
+ * @author Yi
+ * @date 2023-12-22
+ */
+public interface IRmRepairRecordService 
+{
+    /**
+     * 鏌ヨ杩斾慨璁板綍
+     * 
+     * @param id 杩斾慨璁板綍涓婚敭
+     * @return 杩斾慨璁板綍
+     */
+    public RmRepairRecord selectRmRepairRecordById(Long id);
+
+    /**
+     * 鏌ヨ杩斾慨璁板綍鍒楄〃
+     * 
+     * @param rmRepairRecord 杩斾慨璁板綍
+     * @return 杩斾慨璁板綍闆嗗悎
+     */
+    public List<RmRepairRecord> selectRmRepairRecordList(RmRepairRecord rmRepairRecord);
+
+    /**
+     * 鏂板杩斾慨璁板綍
+     * 
+     * @param rmRepairRecord 杩斾慨璁板綍
+     * @return 缁撴灉
+     */
+    public int insertRmRepairRecord(RmRepairRecord rmRepairRecord);
+
+    /**
+     * 淇敼杩斾慨璁板綍
+     * 
+     * @param rmRepairRecord 杩斾慨璁板綍
+     * @return 缁撴灉
+     */
+    public int updateRmRepairRecord(RmRepairRecord rmRepairRecord);
+
+    /**
+     * 鎵归噺鍒犻櫎杩斾慨璁板綍
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑杩斾慨璁板綍涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteRmRepairRecordByIds(Long[] ids);
+
+    /**
+     * 鍒犻櫎杩斾慨璁板綍淇℃伅
+     * 
+     * @param id 杩斾慨璁板綍涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteRmRepairRecordById(Long id);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/rm/repairRecord/service/impl/RmRepairRecordServiceImpl.java b/jcdm-main/src/main/java/com/jcdm/main/rm/repairRecord/service/impl/RmRepairRecordServiceImpl.java
new file mode 100644
index 0000000..55c2979
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/rm/repairRecord/service/impl/RmRepairRecordServiceImpl.java
@@ -0,0 +1,96 @@
+package com.jcdm.main.rm.repairRecord.service.impl;
+
+import java.util.List;
+import com.jcdm.common.utils.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.jcdm.main.rm.repairRecord.mapper.RmRepairRecordMapper;
+import com.jcdm.main.rm.repairRecord.domain.RmRepairRecord;
+import com.jcdm.main.rm.repairRecord.service.IRmRepairRecordService;
+
+/**
+ * 杩斾慨璁板綍Service涓氬姟灞傚鐞�
+ * 
+ * @author Yi
+ * @date 2023-12-22
+ */
+@Service
+public class RmRepairRecordServiceImpl implements IRmRepairRecordService 
+{
+    @Autowired
+    private RmRepairRecordMapper rmRepairRecordMapper;
+
+    /**
+     * 鏌ヨ杩斾慨璁板綍
+     * 
+     * @param id 杩斾慨璁板綍涓婚敭
+     * @return 杩斾慨璁板綍
+     */
+    @Override
+    public RmRepairRecord selectRmRepairRecordById(Long id)
+    {
+        return rmRepairRecordMapper.selectRmRepairRecordById(id);
+    }
+
+    /**
+     * 鏌ヨ杩斾慨璁板綍鍒楄〃
+     * 
+     * @param rmRepairRecord 杩斾慨璁板綍
+     * @return 杩斾慨璁板綍
+     */
+    @Override
+    public List<RmRepairRecord> selectRmRepairRecordList(RmRepairRecord rmRepairRecord)
+    {
+        return rmRepairRecordMapper.selectRmRepairRecordList(rmRepairRecord);
+    }
+
+    /**
+     * 鏂板杩斾慨璁板綍
+     * 
+     * @param rmRepairRecord 杩斾慨璁板綍
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertRmRepairRecord(RmRepairRecord rmRepairRecord)
+    {
+        rmRepairRecord.setCreateTime(DateUtils.getNowDate());
+        return rmRepairRecordMapper.insertRmRepairRecord(rmRepairRecord);
+    }
+
+    /**
+     * 淇敼杩斾慨璁板綍
+     * 
+     * @param rmRepairRecord 杩斾慨璁板綍
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateRmRepairRecord(RmRepairRecord rmRepairRecord)
+    {
+        rmRepairRecord.setUpdateTime(DateUtils.getNowDate());
+        return rmRepairRecordMapper.updateRmRepairRecord(rmRepairRecord);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎杩斾慨璁板綍
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑杩斾慨璁板綍涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteRmRepairRecordByIds(Long[] ids)
+    {
+        return rmRepairRecordMapper.deleteRmRepairRecordByIds(ids);
+    }
+
+    /**
+     * 鍒犻櫎杩斾慨璁板綍淇℃伅
+     * 
+     * @param id 杩斾慨璁板綍涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteRmRepairRecordById(Long id)
+    {
+        return rmRepairRecordMapper.deleteRmRepairRecordById(id);
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/sc/stationConf/controller/ScStationConfController.java b/jcdm-main/src/main/java/com/jcdm/main/sc/stationConf/controller/ScStationConfController.java
new file mode 100644
index 0000000..5b5f8b7
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/sc/stationConf/controller/ScStationConfController.java
@@ -0,0 +1,118 @@
+package com.jcdm.main.sc.stationConf.controller;
+
+import java.util.List;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.jcdm.main.util.IpInfoUtils;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.main.sc.stationConf.domain.ScStationConf;
+import com.jcdm.main.sc.stationConf.service.IScStationConfService;
+import com.jcdm.common.utils.poi.ExcelUtil;
+import com.jcdm.common.core.page.TableDataInfo;
+
+/**
+ * 宸ヤ綅缁堢閰嶇疆Controller
+ * 
+ * @author Yi
+ * @date 2024-01-06
+ */
+@RestController
+@RequestMapping("/sc/stationConf")
+public class ScStationConfController extends BaseController
+{
+    @Autowired
+    private IScStationConfService scStationConfService;
+
+    /**
+     * 鏌ヨ宸ヤ綅缁堢閰嶇疆鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('sc:stationConf:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(ScStationConf scStationConf)
+    {
+        startPage();
+        List<ScStationConf> list = scStationConfService.selectScStationConfList(scStationConf);
+        return getDataTable(list);
+    }
+
+    /**
+     * 瀵煎嚭宸ヤ綅缁堢閰嶇疆鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('sc:stationConf:export')")
+    @Log(title = "宸ヤ綅缁堢閰嶇疆", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, ScStationConf scStationConf)
+    {
+        List<ScStationConf> list = scStationConfService.selectScStationConfList(scStationConf);
+        ExcelUtil<ScStationConf> util = new ExcelUtil<ScStationConf>(ScStationConf.class);
+        util.exportExcel(response, list, "宸ヤ綅缁堢閰嶇疆鏁版嵁");
+    }
+
+    /**
+     * 鑾峰彇宸ヤ綅缁堢閰嶇疆璇︾粏淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('sc:stationConf:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(scStationConfService.selectScStationConfById(id));
+    }
+
+    /**
+     * 鏂板宸ヤ綅缁堢閰嶇疆
+     */
+    @PreAuthorize("@ss.hasPermi('sc:stationConf:add')")
+    @Log(title = "宸ヤ綅缁堢閰嶇疆", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody ScStationConf scStationConf)
+    {
+        return toAjax(scStationConfService.insertScStationConf(scStationConf));
+    }
+
+    /**
+     * 淇敼宸ヤ綅缁堢閰嶇疆
+     */
+    @PreAuthorize("@ss.hasPermi('sc:stationConf:edit')")
+    @Log(title = "宸ヤ綅缁堢閰嶇疆", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody ScStationConf scStationConf)
+    {
+        return toAjax(scStationConfService.updateScStationConf(scStationConf));
+    }
+
+    /**
+     * 鍒犻櫎宸ヤ綅缁堢閰嶇疆
+     */
+    @PreAuthorize("@ss.hasPermi('sc:stationConf:remove')")
+    @Log(title = "宸ヤ綅缁堢閰嶇疆", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(scStationConfService.deleteScStationConfByIds(ids));
+    }
+
+    /**
+     * 鑾峰彇宸ヤ綅缁堢閰嶇疆璇︾粏淇℃伅
+     */
+    @GetMapping(value = "/getIpv4")
+    public AjaxResult getIpv4(HttpServletRequest request)
+    {
+
+        return success(IpInfoUtils.getIpAddr(request));
+    }
+
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/sc/stationConf/domain/ScStationConf.java b/jcdm-main/src/main/java/com/jcdm/main/sc/stationConf/domain/ScStationConf.java
new file mode 100644
index 0000000..3e418c0
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/sc/stationConf/domain/ScStationConf.java
@@ -0,0 +1,193 @@
+package com.jcdm.main.sc.stationConf.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.core.domain.BaseEntity;
+
+/**
+ * 宸ヤ綅缁堢閰嶇疆瀵硅薄 sc_station_conf
+ * 
+ * @author Yi
+ * @date 2024-01-06
+ */
+public class ScStationConf extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 涓婚敭id */
+    private Long id;
+
+    /** 宸ュ簭缂栧彿 */
+    @Excel(name = "宸ュ簭缂栧彿")
+    private String processesCode;
+
+    /** 宸ュ簭鍚嶇О */
+    @Excel(name = "宸ュ簭鍚嶇О")
+    private String processesName;
+
+    /** 宸ュ簭绫诲瀷 */
+    @Excel(name = "宸ュ簭绫诲瀷")
+    private String processesType;
+
+    /** IP鍦板潃 */
+    @Excel(name = "IP鍦板潃")
+    private String ipAddress;
+
+    /** 棰勭暀瀛楁1 */
+    @Excel(name = "棰勭暀瀛楁1")
+    private String spareField1;
+
+    /** 棰勭暀瀛楁2 */
+    @Excel(name = "棰勭暀瀛楁2")
+    private String spareField2;
+
+    /** 棰勭暀瀛楁3 */
+    @Excel(name = "棰勭暀瀛楁3")
+    private String spareField3;
+
+    /** 棰勭暀瀛楁4 */
+    @Excel(name = "棰勭暀瀛楁4")
+    private String spareField4;
+
+    /** 鍒涘缓鐢ㄦ埛 */
+    @Excel(name = "鍒涘缓鐢ㄦ埛")
+    private String createUser;
+
+    /** 鏇存敼鐢ㄦ埛 */
+    @Excel(name = "鏇存敼鐢ㄦ埛")
+    private String updateUser;
+
+    /** 澶囨敞 */
+    @Excel(name = "澶囨敞")
+    private String remarks;
+
+    public void setId(Long id) 
+    {
+        this.id = id;
+    }
+
+    public Long getId() 
+    {
+        return id;
+    }
+    public void setProcessesCode(String processesCode) 
+    {
+        this.processesCode = processesCode;
+    }
+
+    public String getProcessesCode() 
+    {
+        return processesCode;
+    }
+    public void setProcessesName(String processesName) 
+    {
+        this.processesName = processesName;
+    }
+
+    public String getProcessesName() 
+    {
+        return processesName;
+    }
+    public void setProcessesType(String processesType) 
+    {
+        this.processesType = processesType;
+    }
+
+    public String getProcessesType() 
+    {
+        return processesType;
+    }
+    public void setIpAddress(String ipAddress) 
+    {
+        this.ipAddress = ipAddress;
+    }
+
+    public String getIpAddress() 
+    {
+        return ipAddress;
+    }
+    public void setSpareField1(String spareField1) 
+    {
+        this.spareField1 = spareField1;
+    }
+
+    public String getSpareField1() 
+    {
+        return spareField1;
+    }
+    public void setSpareField2(String spareField2) 
+    {
+        this.spareField2 = spareField2;
+    }
+
+    public String getSpareField2() 
+    {
+        return spareField2;
+    }
+    public void setSpareField3(String spareField3) 
+    {
+        this.spareField3 = spareField3;
+    }
+
+    public String getSpareField3() 
+    {
+        return spareField3;
+    }
+    public void setSpareField4(String spareField4) 
+    {
+        this.spareField4 = spareField4;
+    }
+
+    public String getSpareField4() 
+    {
+        return spareField4;
+    }
+    public void setCreateUser(String createUser) 
+    {
+        this.createUser = createUser;
+    }
+
+    public String getCreateUser() 
+    {
+        return createUser;
+    }
+    public void setUpdateUser(String updateUser) 
+    {
+        this.updateUser = updateUser;
+    }
+
+    public String getUpdateUser() 
+    {
+        return updateUser;
+    }
+    public void setRemarks(String remarks) 
+    {
+        this.remarks = remarks;
+    }
+
+    public String getRemarks() 
+    {
+        return remarks;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("processesCode", getProcessesCode())
+            .append("processesName", getProcessesName())
+            .append("processesType", getProcessesType())
+            .append("ipAddress", getIpAddress())
+            .append("spareField1", getSpareField1())
+            .append("spareField2", getSpareField2())
+            .append("spareField3", getSpareField3())
+            .append("spareField4", getSpareField4())
+            .append("createUser", getCreateUser())
+            .append("createTime", getCreateTime())
+            .append("updateUser", getUpdateUser())
+            .append("updateTime", getUpdateTime())
+            .append("remarks", getRemarks())
+            .toString();
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/sc/stationConf/mapper/ScStationConfMapper.java b/jcdm-main/src/main/java/com/jcdm/main/sc/stationConf/mapper/ScStationConfMapper.java
new file mode 100644
index 0000000..1945691
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/sc/stationConf/mapper/ScStationConfMapper.java
@@ -0,0 +1,61 @@
+package com.jcdm.main.sc.stationConf.mapper;
+
+import java.util.List;
+import com.jcdm.main.sc.stationConf.domain.ScStationConf;
+
+/**
+ * 宸ヤ綅缁堢閰嶇疆Mapper鎺ュ彛
+ * 
+ * @author Yi
+ * @date 2024-01-06
+ */
+public interface ScStationConfMapper 
+{
+    /**
+     * 鏌ヨ宸ヤ綅缁堢閰嶇疆
+     * 
+     * @param id 宸ヤ綅缁堢閰嶇疆涓婚敭
+     * @return 宸ヤ綅缁堢閰嶇疆
+     */
+    public ScStationConf selectScStationConfById(Long id);
+
+    /**
+     * 鏌ヨ宸ヤ綅缁堢閰嶇疆鍒楄〃
+     * 
+     * @param scStationConf 宸ヤ綅缁堢閰嶇疆
+     * @return 宸ヤ綅缁堢閰嶇疆闆嗗悎
+     */
+    public List<ScStationConf> selectScStationConfList(ScStationConf scStationConf);
+
+    /**
+     * 鏂板宸ヤ綅缁堢閰嶇疆
+     * 
+     * @param scStationConf 宸ヤ綅缁堢閰嶇疆
+     * @return 缁撴灉
+     */
+    public int insertScStationConf(ScStationConf scStationConf);
+
+    /**
+     * 淇敼宸ヤ綅缁堢閰嶇疆
+     * 
+     * @param scStationConf 宸ヤ綅缁堢閰嶇疆
+     * @return 缁撴灉
+     */
+    public int updateScStationConf(ScStationConf scStationConf);
+
+    /**
+     * 鍒犻櫎宸ヤ綅缁堢閰嶇疆
+     * 
+     * @param id 宸ヤ綅缁堢閰嶇疆涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteScStationConfById(Long id);
+
+    /**
+     * 鎵归噺鍒犻櫎宸ヤ綅缁堢閰嶇疆
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteScStationConfByIds(Long[] ids);
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/sc/stationConf/service/IScStationConfService.java b/jcdm-main/src/main/java/com/jcdm/main/sc/stationConf/service/IScStationConfService.java
new file mode 100644
index 0000000..e3daefd
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/sc/stationConf/service/IScStationConfService.java
@@ -0,0 +1,63 @@
+package com.jcdm.main.sc.stationConf.service;
+
+import java.util.List;
+import com.jcdm.main.sc.stationConf.domain.ScStationConf;
+
+/**
+ * 宸ヤ綅缁堢閰嶇疆Service鎺ュ彛
+ * 
+ * @author Yi
+ * @date 2024-01-06
+ */
+public interface IScStationConfService 
+{
+    /**
+     * 鏌ヨ宸ヤ綅缁堢閰嶇疆
+     * 
+     * @param id 宸ヤ綅缁堢閰嶇疆涓婚敭
+     * @return 宸ヤ綅缁堢閰嶇疆
+     */
+    public ScStationConf selectScStationConfById(Long id);
+
+    /**
+     * 鏌ヨ宸ヤ綅缁堢閰嶇疆鍒楄〃
+     * 
+     * @param scStationConf 宸ヤ綅缁堢閰嶇疆
+     * @return 宸ヤ綅缁堢閰嶇疆闆嗗悎
+     */
+    public List<ScStationConf> selectScStationConfList(ScStationConf scStationConf);
+
+    /**
+     * 鏂板宸ヤ綅缁堢閰嶇疆
+     * 
+     * @param scStationConf 宸ヤ綅缁堢閰嶇疆
+     * @return 缁撴灉
+     */
+    public int insertScStationConf(ScStationConf scStationConf);
+
+    /**
+     * 淇敼宸ヤ綅缁堢閰嶇疆
+     * 
+     * @param scStationConf 宸ヤ綅缁堢閰嶇疆
+     * @return 缁撴灉
+     */
+    public int updateScStationConf(ScStationConf scStationConf);
+
+    /**
+     * 鎵归噺鍒犻櫎宸ヤ綅缁堢閰嶇疆
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑宸ヤ綅缁堢閰嶇疆涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteScStationConfByIds(Long[] ids);
+
+    /**
+     * 鍒犻櫎宸ヤ綅缁堢閰嶇疆淇℃伅
+     * 
+     * @param id 宸ヤ綅缁堢閰嶇疆涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteScStationConfById(Long id);
+
+    String getIpv4();
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/sc/stationConf/service/impl/ScStationConfServiceImpl.java b/jcdm-main/src/main/java/com/jcdm/main/sc/stationConf/service/impl/ScStationConfServiceImpl.java
new file mode 100644
index 0000000..c269781
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/sc/stationConf/service/impl/ScStationConfServiceImpl.java
@@ -0,0 +1,109 @@
+package com.jcdm.main.sc.stationConf.service.impl;
+
+import java.net.InetAddress;
+import java.util.List;
+import com.jcdm.common.utils.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.jcdm.main.sc.stationConf.mapper.ScStationConfMapper;
+import com.jcdm.main.sc.stationConf.domain.ScStationConf;
+import com.jcdm.main.sc.stationConf.service.IScStationConfService;
+
+/**
+ * 宸ヤ綅缁堢閰嶇疆Service涓氬姟灞傚鐞�
+ * 
+ * @author Yi
+ * @date 2024-01-06
+ */
+@Service
+public class ScStationConfServiceImpl implements IScStationConfService 
+{
+    @Autowired
+    private ScStationConfMapper scStationConfMapper;
+
+    /**
+     * 鏌ヨ宸ヤ綅缁堢閰嶇疆
+     * 
+     * @param id 宸ヤ綅缁堢閰嶇疆涓婚敭
+     * @return 宸ヤ綅缁堢閰嶇疆
+     */
+    @Override
+    public ScStationConf selectScStationConfById(Long id)
+    {
+        return scStationConfMapper.selectScStationConfById(id);
+    }
+
+    /**
+     * 鏌ヨ宸ヤ綅缁堢閰嶇疆鍒楄〃
+     * 
+     * @param scStationConf 宸ヤ綅缁堢閰嶇疆
+     * @return 宸ヤ綅缁堢閰嶇疆
+     */
+    @Override
+    public List<ScStationConf> selectScStationConfList(ScStationConf scStationConf)
+    {
+        return scStationConfMapper.selectScStationConfList(scStationConf);
+    }
+
+    /**
+     * 鏂板宸ヤ綅缁堢閰嶇疆
+     * 
+     * @param scStationConf 宸ヤ綅缁堢閰嶇疆
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertScStationConf(ScStationConf scStationConf)
+    {
+        scStationConf.setCreateTime(DateUtils.getNowDate());
+        return scStationConfMapper.insertScStationConf(scStationConf);
+    }
+
+    /**
+     * 淇敼宸ヤ綅缁堢閰嶇疆
+     * 
+     * @param scStationConf 宸ヤ綅缁堢閰嶇疆
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateScStationConf(ScStationConf scStationConf)
+    {
+        scStationConf.setUpdateTime(DateUtils.getNowDate());
+        return scStationConfMapper.updateScStationConf(scStationConf);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎宸ヤ綅缁堢閰嶇疆
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑宸ヤ綅缁堢閰嶇疆涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteScStationConfByIds(Long[] ids)
+    {
+        return scStationConfMapper.deleteScStationConfByIds(ids);
+    }
+
+    /**
+     * 鍒犻櫎宸ヤ綅缁堢閰嶇疆淇℃伅
+     * 
+     * @param id 宸ヤ綅缁堢閰嶇疆涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteScStationConfById(Long id)
+    {
+        return scStationConfMapper.deleteScStationConfById(id);
+    }
+
+    @Override
+    public String getIpv4() {
+        String ipv4 = "";
+        try {
+            InetAddress localhost = InetAddress.getLocalHost();
+            ipv4 = localhost.getHostAddress();
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+        return ipv4;
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/util/IpInfoUtils.java b/jcdm-main/src/main/java/com/jcdm/main/util/IpInfoUtils.java
new file mode 100644
index 0000000..93c7161
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/util/IpInfoUtils.java
@@ -0,0 +1,63 @@
+package com.jcdm.main.util;
+
+import javax.servlet.http.HttpServletRequest;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * ip宸ュ叿绫�
+ *
+ * @author fengshuonan
+ * @Date 2018/9/27 涓婂崍10:47
+ */
+public class IpInfoUtils {
+
+    /**
+     * 鑾峰彇瀹㈡埛绔疘P鍦板潃
+     */
+    public static String getIpAddr(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.getRemoteAddr();
+            if (ip.equals("127.0.0.1")) {
+                //鏍规嵁缃戝崱鍙栨湰鏈洪厤缃殑IP
+                InetAddress inet = null;
+                try {
+                    inet = InetAddress.getLocalHost();
+                } catch (UnknownHostException e) {
+                    e.printStackTrace();
+                }
+                ip = inet.getHostAddress();
+            }
+        }
+        // 瀵逛簬閫氳繃澶氫釜浠g悊鐨勬儏鍐碉紝绗竴涓狪P涓哄鎴风鐪熷疄IP,澶氫釜IP鎸夌収','鍒嗗壊
+        if (ip != null && ip.length() > 15) {
+            if (ip.indexOf(",") > 0) {
+                ip = ip.substring(0, ip.indexOf(","));
+            }
+        }
+
+        if ("0:0:0:0:0:0:0:1".equals(ip)) {
+            ip = "127.0.0.1";
+        }
+
+        return ip;
+    }
+
+    /**
+     * 鑾峰彇瀹㈡埛绔富鏈哄悕绉�
+     */
+    public static String getHostName() {
+        try {
+            return InetAddress.getLocalHost().getHostName();
+        } catch (UnknownHostException e) {
+        }
+        return "鏈煡";
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/webservice/Item.java b/jcdm-main/src/main/java/com/jcdm/main/webservice/Item.java
new file mode 100644
index 0000000..b3ab39a
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/webservice/Item.java
@@ -0,0 +1,25 @@
+package com.jcdm.main.webservice;
+
+import lombok.Data;
+
+@Data
+public class Item {
+    private String MAKTX;
+    private String FEVOR;
+    private String WERKS;
+    private String LGORT;
+    private String ZHTH;
+    private String GSTRP;
+    private String AUFNR;
+    private String PSMNG;
+    private String DISPO;
+    private String ZSCTZD;
+    private String PLNBEZ;
+    private String ZSTAT;
+    private String DAUAT;
+    private String ZWS;
+    private String KDAUF;
+    private String ZUSER;
+    private String ZDATE;
+    private String FERTH;
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/webservice/ItemList.java b/jcdm-main/src/main/java/com/jcdm/main/webservice/ItemList.java
new file mode 100644
index 0000000..1a4af30
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/webservice/ItemList.java
@@ -0,0 +1,22 @@
+package com.jcdm.main.webservice;
+
+import java.util.List;
+
+public class ItemList {
+    private List<Item> item;
+
+    // 娣诲姞鏋勯�犲嚱鏁板拰getter/setter鏂规硶
+
+    // 鏋勯�犲嚱鏁�
+    public ItemList() {
+    }
+
+    // Getter鍜孲etter鏂规硶
+    public List<Item> getItem() {
+        return item;
+    }
+
+    public void setItem(List<Item> item) {
+        this.item = item;
+    }
+}
diff --git a/jcdm-main/src/main/java/com/jcdm/main/webservice/test.java b/jcdm-main/src/main/java/com/jcdm/main/webservice/test.java
new file mode 100644
index 0000000..30353ed
--- /dev/null
+++ b/jcdm-main/src/main/java/com/jcdm/main/webservice/test.java
@@ -0,0 +1,93 @@
+package com.jcdm.main.webservice;
+
+
+import java.io.InputStream;
+import java.util.List;
+
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import cn.hutool.json.XML;
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.UsernamePasswordCredentials;
+import org.apache.commons.httpclient.auth.AuthScope;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.methods.RequestEntity;
+import org.apache.commons.httpclient.methods.StringRequestEntity;
+import org.apache.commons.io.IOUtils;
+
+
+public class test {
+
+    public static void main(String[] args) throws Exception {
+        String serviceUrl = "http://podqapp.cfmoto.com.cn:50200/XISOAPAdapter/MessageServlet?senderParty=&senderService=BC_MES&receiverParty=&receiverService=&interface=SI_ZPP_CF_MES_005_SYN_OUT&interfaceNamespace=http://cfmoto.com/xi/MES";
+
+        String content = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:urn=\"urn:sap-com:document:sap:rfc:functions\">\n" +
+                "   <soapenv:Header/>\n" +
+                "   <soapenv:Body>\n" +
+                "      <urn:ZPP_CF_MES_005>\n" +
+                "         <!--Optional:-->\n" +
+                "         <IV_WERKS>1000</IV_WERKS>\n" +
+                "         <!--Optional:-->\n" +
+                "         <IV_ZSCTZD>A0055577</IV_ZSCTZD>\n" +
+                "      </urn:ZPP_CF_MES_005>\n" +
+                "   </soapenv:Body>\n" +
+                "</soapenv:Envelope>";
+        // HttpClient鍙戦�丼OAP璇锋眰
+        int timeout = 10000;
+        HttpClient client = new HttpClient();
+        //濡傛灉闇�瑕佺敤鎴峰悕瀵嗙爜楠岃瘉锛涗笉闇�瑕侀獙璇佺櫥褰曞垯涓嶉渶瑕佷互涓�4琛�
+        String username = "POMESUSER";
+        String password = "12345tgb";
+        UsernamePasswordCredentials creds = new UsernamePasswordCredentials(username, password);
+        client.getState().setCredentials(AuthScope.ANY, creds);
+
+        PostMethod postMethod = new PostMethod(serviceUrl);
+        // 璁剧疆杩炴帴瓒呮椂
+        client.getHttpConnectionManager().getParams().setConnectionTimeout(timeout);
+        // 璁剧疆璇诲彇鏃堕棿瓒呮椂
+        client.getHttpConnectionManager().getParams().setSoTimeout(timeout);
+        // 鐒跺悗鎶奡oap璇锋眰鏁版嵁娣诲姞鍒癙ostMethod涓�
+        RequestEntity requestEntity = new StringRequestEntity(content, "text/xml", "UTF-8");
+
+        // 璁剧疆璇锋眰澶撮儴锛屽惁鍒欏彲鑳戒細鎶� 鈥渘o SOAPAction header鈥� 鐨勯敊璇�
+        postMethod.setRequestHeader("SOAPAction", "");
+        // 璁剧疆璇锋眰浣�
+        postMethod.setRequestEntity(requestEntity);
+        int status = client.executeMethod(postMethod);
+
+        if (status == 200) {// 鎴愬姛
+            InputStream is = postMethod.getResponseBodyAsStream();
+            // 鑾峰彇璇锋眰缁撴灉瀛楃涓�
+            String result = IOUtils.toString(is);
+            String jsonStr = xmlToJSON2(result);
+            Gson gson = new Gson();
+            // 灏唈son瀛楃涓茶浆鎹㈡垚瀵硅薄
+            ItemList itemList = gson.fromJson(jsonStr, ItemList.class);
+            System.out.println("杩斿洖缁撴灉:" + result);
+        } else {
+            System.out.println("閿欒浠g爜锛�" + status + ":" + postMethod.getResponseBodyAsString());
+        }
+    }
+
+    /**
+     * 鏂瑰紡--璐�
+     * 浣跨敤hutool宸ュ叿鍖呬腑鐨勫伐鍏疯浆鍖�
+     * @param xmlStr
+     * @return
+     */
+    public static String xmlToJSON2(String xmlStr){
+        JSONObject jsonObject1 = cn.hutool.json.XML.toJSONObject(xmlStr, true);
+
+        Gson gson = new Gson();
+        JsonObject jsonObject2 = gson.fromJson(jsonObject1.toString(), JsonObject.class);
+        JsonObject etData = jsonObject2
+                .getAsJsonObject("SOAP:Envelope")
+                .getAsJsonObject("SOAP:Body")
+                .getAsJsonObject("n0:ZPP_CF_MES_005.Response")
+                .getAsJsonObject("ET_DATA");
+        return etData.toString();
+    }
+
+}
diff --git a/jcdm-main/src/main/resources/mapper/bs/beatSetting/BsBeatSettingMapper.xml b/jcdm-main/src/main/resources/mapper/bs/beatSetting/BsBeatSettingMapper.xml
new file mode 100644
index 0000000..f0a65db
--- /dev/null
+++ b/jcdm-main/src/main/resources/mapper/bs/beatSetting/BsBeatSettingMapper.xml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.main.bs.beatSetting.mapper.BsBeatSettingMapper">
+    
+    <resultMap type="BsBeatSetting" id="BsBeatSettingResult">
+        <result property="id"    column="id"    />
+        <result property="productCode"    column="product_code"    />
+        <result property="productName"    column="product_name"    />
+        <result property="beat"    column="beat"    />
+        <result property="spareField1"    column="spare_field_1"    />
+        <result property="spareField2"    column="spare_field_2"    />
+        <result property="remark"    column="remark"    />
+        <result property="createUser"    column="create_user"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateUser"    column="update_user"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="dataSource"    column="data_source"    />
+    </resultMap>
+
+    <sql id="selectBsBeatSettingVo">
+        select id, product_code, product_name, beat, spare_field_1, spare_field_2, remark, create_user, create_time, update_user, update_time, data_source from bs_beat_setting
+    </sql>
+
+    <select id="selectBsBeatSettingList" parameterType="BsBeatSetting" resultMap="BsBeatSettingResult">
+        <include refid="selectBsBeatSettingVo"/>
+        <where>  
+            <if test="productCode != null  and productCode != ''"> and product_code = #{productCode}</if>
+            <if test="productName != null  and productName != ''"> and product_name like concat('%', #{productName}, '%')</if>
+            <if test="beat != null  and beat != ''"> and beat = #{beat}</if>
+            <if test="spareField1 != null  and spareField1 != ''"> and spare_field_1 = #{spareField1}</if>
+            <if test="spareField2 != null  and spareField2 != ''"> and spare_field_2 = #{spareField2}</if>
+            <if test="createUser != null  and createUser != ''"> and create_user = #{createUser}</if>
+            <if test="updateUser != null  and updateUser != ''"> and update_user = #{updateUser}</if>
+            <if test="dataSource != null  and dataSource != ''"> and data_source = #{dataSource}</if>
+        </where>
+    </select>
+    
+    <select id="selectBsBeatSettingById" parameterType="Long" resultMap="BsBeatSettingResult">
+        <include refid="selectBsBeatSettingVo"/>
+        where id = #{id}
+    </select>
+        
+    <insert id="insertBsBeatSetting" parameterType="BsBeatSetting" useGeneratedKeys="true" keyProperty="id">
+        insert into bs_beat_setting
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="productCode != null">product_code,</if>
+            <if test="productName != null">product_name,</if>
+            <if test="beat != null and beat != ''">beat,</if>
+            <if test="spareField1 != null">spare_field_1,</if>
+            <if test="spareField2 != null">spare_field_2,</if>
+            <if test="remark != null">remark,</if>
+            <if test="createUser != null">create_user,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateUser != null">update_user,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="dataSource != null">data_source,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="productCode != null">#{productCode},</if>
+            <if test="productName != null">#{productName},</if>
+            <if test="beat != null and beat != ''">#{beat},</if>
+            <if test="spareField1 != null">#{spareField1},</if>
+            <if test="spareField2 != null">#{spareField2},</if>
+            <if test="remark != null">#{remark},</if>
+            <if test="createUser != null">#{createUser},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateUser != null">#{updateUser},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="dataSource != null">#{dataSource},</if>
+         </trim>
+    </insert>
+
+    <update id="updateBsBeatSetting" parameterType="BsBeatSetting">
+        update bs_beat_setting
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="productCode != null">product_code = #{productCode},</if>
+            <if test="productName != null">product_name = #{productName},</if>
+            <if test="beat != null and beat != ''">beat = #{beat},</if>
+            <if test="spareField1 != null">spare_field_1 = #{spareField1},</if>
+            <if test="spareField2 != null">spare_field_2 = #{spareField2},</if>
+            <if test="remark != null">remark = #{remark},</if>
+            <if test="createUser != null">create_user = #{createUser},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateUser != null">update_user = #{updateUser},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="dataSource != null">data_source = #{dataSource},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteBsBeatSettingById" parameterType="Long">
+        delete from bs_beat_setting where id = #{id}
+    </delete>
+
+    <delete id="deleteBsBeatSettingByIds" parameterType="String">
+        delete from bs_beat_setting where id in 
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>
\ No newline at end of file
diff --git a/jcdm-main/src/main/resources/mapper/bs/formula/BsFormulaInfoMapper.xml b/jcdm-main/src/main/resources/mapper/bs/formula/BsFormulaInfoMapper.xml
new file mode 100644
index 0000000..6b6a0d2
--- /dev/null
+++ b/jcdm-main/src/main/resources/mapper/bs/formula/BsFormulaInfoMapper.xml
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.main.bs.formula.mapper.BsFormulaInfoMapper">
+    
+    <resultMap type="BsFormulaInfo" id="BsFormulaInfoResult">
+        <result property="id"    column="id"    />
+        <result property="formulaCode"    column="formula_code"    />
+        <result property="formulaName"    column="formula_name"    />
+        <result property="status"    column="status"    />
+        <result property="productCode"    column="product_code"    />
+        <result property="remark"    column="remark"    />
+        <result property="createUser"    column="create_user"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateUser"    column="update_user"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="spareField1"    column="spare_field_1"    />
+        <result property="spareField2"    column="spare_field_2"    />
+        <result property="spareField3"    column="spare_field_3"    />
+        <result property="spareField4"    column="spare_field_4"    />
+    </resultMap>
+
+    <sql id="selectBsFormulaInfoVo">
+        select id, formula_code, formula_name, status, product_code, remark, create_user, create_time, update_user, update_time, spare_field_1, spare_field_2, spare_field_3, spare_field_4 from bs_formula_info
+    </sql>
+
+    <select id="selectBsFormulaInfoList" parameterType="BsFormulaInfo" resultMap="BsFormulaInfoResult">
+        <include refid="selectBsFormulaInfoVo"/>
+        <where>  
+            <if test="formulaCode != null  and formulaCode != ''"> and formula_code like concat('%', #{formulaCode}, '%')</if>
+            <if test="formulaName != null  and formulaName != ''"> and formula_name like concat('%', #{formulaName}, '%')</if>
+            <if test="status != null  and status != ''"> and status = #{status}</if>
+            <if test="productCode != null  and productCode != ''"> and product_code like concat('%', #{productCode}, '%')</if>
+        </where>
+    </select>
+    
+    <select id="selectBsFormulaInfoById" parameterType="Long" resultMap="BsFormulaInfoResult">
+        <include refid="selectBsFormulaInfoVo"/>
+        where id = #{id}
+    </select>
+        
+    <insert id="insertBsFormulaInfo" parameterType="BsFormulaInfo">
+        insert into bs_formula_info
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="id != null">id,</if>
+            <if test="formulaCode != null and formulaCode != ''">formula_code,</if>
+            <if test="formulaName != null">formula_name,</if>
+            <if test="status != null and status != ''">status,</if>
+            <if test="productCode != null and productCode != ''">product_code,</if>
+            <if test="remark != null">remark,</if>
+            <if test="createUser != null">create_user,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateUser != null">update_user,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="spareField1 != null">spare_field_1,</if>
+            <if test="spareField2 != null">spare_field_2,</if>
+            <if test="spareField3 != null">spare_field_3,</if>
+            <if test="spareField4 != null">spare_field_4,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="id != null">#{id},</if>
+            <if test="formulaCode != null and formulaCode != ''">#{formulaCode},</if>
+            <if test="formulaName != null">#{formulaName},</if>
+            <if test="status != null and status != ''">#{status},</if>
+            <if test="productCode != null and productCode != ''">#{productCode},</if>
+            <if test="remark != null">#{remark},</if>
+            <if test="createUser != null">#{createUser},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateUser != null">#{updateUser},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="spareField1 != null">#{spareField1},</if>
+            <if test="spareField2 != null">#{spareField2},</if>
+            <if test="spareField3 != null">#{spareField3},</if>
+            <if test="spareField4 != null">#{spareField4},</if>
+         </trim>
+    </insert>
+
+    <update id="updateBsFormulaInfo" parameterType="BsFormulaInfo">
+        update bs_formula_info
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="formulaCode != null and formulaCode != ''">formula_code = #{formulaCode},</if>
+            <if test="formulaName != null">formula_name = #{formulaName},</if>
+            <if test="status != null and status != ''">status = #{status},</if>
+            <if test="productCode != null and productCode != ''">product_code = #{productCode},</if>
+            <if test="remark != null">remark = #{remark},</if>
+            <if test="createUser != null">create_user = #{createUser},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateUser != null">update_user = #{updateUser},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="spareField1 != null">spare_field_1 = #{spareField1},</if>
+            <if test="spareField2 != null">spare_field_2 = #{spareField2},</if>
+            <if test="spareField3 != null">spare_field_3 = #{spareField3},</if>
+            <if test="spareField4 != null">spare_field_4 = #{spareField4},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteBsFormulaInfoById" parameterType="Long">
+        delete from bs_formula_info where id = #{id}
+    </delete>
+
+    <delete id="deleteBsFormulaInfoByIds" parameterType="String">
+        delete from bs_formula_info where id in 
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>
\ No newline at end of file
diff --git a/jcdm-main/src/main/resources/mapper/bs/formulaChild/BsFormulaChildInfoMapper.xml b/jcdm-main/src/main/resources/mapper/bs/formulaChild/BsFormulaChildInfoMapper.xml
new file mode 100644
index 0000000..d9720a9
--- /dev/null
+++ b/jcdm-main/src/main/resources/mapper/bs/formulaChild/BsFormulaChildInfoMapper.xml
@@ -0,0 +1,185 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.main.bs.formulaChild.mapper.BsFormulaChildInfoMapper">
+    
+    <resultMap type="BsFormulaChildInfo" id="BsFormulaChildInfoResult">
+        <result property="id"    column="id"    />
+        <result property="workshopCode"    column="workshop_code"    />
+        <result property="lineCode"    column="line_code"    />
+        <result property="processesCode"    column="processes_code"    />
+        <result property="productCode"    column="product_code"    />
+        <result property="operationSteps"    column="operation_steps"    />
+        <result property="techRequirement"    column="tech_requirement"    />
+        <result property="operationType"    column="operation_type"    />
+        <result property="stepSort"    column="step_sort"    />
+        <result property="paramCode"    column="param_code"    />
+        <result property="materialCode"    column="material_code"    />
+        <result property="formulaCode"    column="formula_code"    />
+        <result property="picture"    column="picture"    />
+        <result property="remarks"    column="remarks"    />
+        <result property="createUser"    column="create_user"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateUser"    column="update_user"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="spareField1"    column="spare_field_1"    />
+        <result property="spareField2"    column="spare_field_2"    />
+        <result property="spareField3"    column="spare_field_3"    />
+        <result property="spareField4"    column="spare_field_4"    />
+        <result property="collectData"    column="collect_data"    />
+        <result property="results"    column="results"    />
+    </resultMap>
+
+    <sql id="selectBsFormulaChildInfoVo">
+        select id, workshop_code, line_code, processes_code, product_code, operation_steps, tech_requirement, operation_type, step_sort, param_code, material_code, formula_code, picture, remarks, create_user, create_time, update_user, update_time, spare_field_1, spare_field_2, spare_field_3, spare_field_4, collect_data, results from bs_formula_child_info
+    </sql>
+
+    <select id="selectBsFormulaChildInfoList" parameterType="BsFormulaChildInfo" resultMap="BsFormulaChildInfoResult">
+        <include refid="selectBsFormulaChildInfoVo"/>
+        <where>  
+            <if test="workshopCode != null  and workshopCode != ''"> and workshop_code like concat('%', #{workshopCode}, '%')</if>
+            <if test="lineCode != null  and lineCode != ''"> and line_code like concat('%', #{lineCode}, '%')</if>
+            <if test="processesCode != null  and processesCode != ''"> and processes_code like concat('%', #{processesCode}, '%')</if>
+            <if test="productCode != null  and productCode != ''"> and product_code like concat('%', #{productCode}, '%')</if>
+            <if test="operationType != null  and operationType != ''"> and operation_type like concat('%', #{operationType}, '%')</if>
+            <if test="formulaCode != null  and formulaCode != ''"> and formula_code like concat('%', #{formulaCode}, '%')</if>
+            <if test="collectData != null  and collectData != ''"> and collect_data = #{collectData}</if>
+            <if test="results != null  and result != ''"> and result = #{results}</if>
+            <if test="materialCode != null  and materialCode != ''"> and material_code = #{materialCode}</if>
+
+        </where>
+        ORDER BY step_sort ASC
+    </select>
+    
+    <select id="selectBsFormulaChildInfoById" parameterType="Long" resultMap="BsFormulaChildInfoResult">
+        <include refid="selectBsFormulaChildInfoVo"/>
+        where id = #{id}
+    </select>
+        
+    <insert id="insertBsFormulaChildInfo" parameterType="BsFormulaChildInfo" useGeneratedKeys="true" keyProperty="id">
+        insert into bs_formula_child_info
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="workshopCode != null">workshop_code,</if>
+            <if test="lineCode != null">line_code,</if>
+            <if test="processesCode != null">processes_code,</if>
+            <if test="productCode != null">product_code,</if>
+            <if test="operationSteps != null">operation_steps,</if>
+            <if test="techRequirement != null">tech_requirement,</if>
+            <if test="operationType != null">operation_type,</if>
+            <if test="stepSort != null">step_sort,</if>
+            <if test="paramCode != null">param_code,</if>
+            <if test="materialCode != null">material_code,</if>
+            <if test="formulaCode != null">formula_code,</if>
+            <if test="picture != null">picture,</if>
+            <if test="remarks != null">remarks,</if>
+            <if test="createUser != null">create_user,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateUser != null">update_user,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="spareField1 != null">spare_field_1,</if>
+            <if test="spareField2 != null">spare_field_2,</if>
+            <if test="spareField3 != null">spare_field_3,</if>
+            <if test="spareField4 != null">spare_field_4,</if>
+            <if test="collectData != null">collect_data,</if>
+            <if test="results != null">results,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="workshopCode != null">#{workshopCode},</if>
+            <if test="lineCode != null">#{lineCode},</if>
+            <if test="processesCode != null">#{processesCode},</if>
+            <if test="productCode != null">#{productCode},</if>
+            <if test="operationSteps != null">#{operationSteps},</if>
+            <if test="techRequirement != null">#{techRequirement},</if>
+            <if test="operationType != null">#{operationType},</if>
+            <if test="stepSort != null">#{stepSort},</if>
+            <if test="paramCode != null">#{paramCode},</if>
+            <if test="materialCode != null">#{materialCode},</if>
+            <if test="formulaCode != null">#{formulaCode},</if>
+            <if test="picture != null">#{picture},</if>
+            <if test="remarks != null">#{remarks},</if>
+            <if test="createUser != null">#{createUser},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateUser != null">#{updateUser},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="spareField1 != null">#{spareField1},</if>
+            <if test="spareField2 != null">#{spareField2},</if>
+            <if test="spareField3 != null">#{spareField3},</if>
+            <if test="spareField4 != null">#{spareField4},</if>
+            <if test="collectData != null">collect_data,</if>
+            <if test="results != null">results,</if>
+         </trim>
+    </insert>
+
+    <update id="updateBsFormulaChildInfo" parameterType="BsFormulaChildInfo">
+        update bs_formula_child_info
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="workshopCode != null">workshop_code = #{workshopCode},</if>
+            <if test="lineCode != null">line_code = #{lineCode},</if>
+            <if test="processesCode != null">processes_code = #{processesCode},</if>
+            <if test="productCode != null">product_code = #{productCode},</if>
+            <if test="operationSteps != null">operation_steps = #{operationSteps},</if>
+            <if test="techRequirement != null">tech_requirement = #{techRequirement},</if>
+            <if test="operationType != null">operation_type = #{operationType},</if>
+            <if test="stepSort != null">step_sort = #{stepSort},</if>
+            <if test="paramCode != null">param_code = #{paramCode},</if>
+            <if test="materialCode != null">material_code = #{materialCode},</if>
+            <if test="formulaCode != null">formula_code = #{formulaCode},</if>
+            <if test="picture != null">picture = #{picture},</if>
+            <if test="remarks != null">remarks = #{remarks},</if>
+            <if test="createUser != null">create_user = #{createUser},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateUser != null">update_user = #{updateUser},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="spareField1 != null">spare_field_1 = #{spareField1},</if>
+            <if test="spareField2 != null">spare_field_2 = #{spareField2},</if>
+            <if test="spareField3 != null">spare_field_3 = #{spareField3},</if>
+            <if test="spareField4 != null">spare_field_4 = #{spareField4},</if>
+            <if test="collectData != null">collect_data = #{collectData},</if>
+            <if test="results != null">results = #{results},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteBsFormulaChildInfoById" parameterType="Long">
+        delete from bs_formula_child_info where id = #{id}
+    </delete>
+
+    <delete id="deleteBsFormulaChildInfoByIds" parameterType="String">
+        delete from bs_formula_child_info where id in 
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+
+    <select id="selectBsFormulaChildInfoByTypeTopOne" parameterType="BsFormulaChildInfo" resultMap="BsFormulaChildInfoResult">
+        SELECT
+            TOP 1 *
+        FROM
+            bs_formula_child_info
+        WHERE NOT results = 'OK'
+          AND product_code =  #{productCode}
+          AND processes_code = #{processesCode}
+          AND operation_type = #{operationType}
+        ORDER BY step_sort ASC
+    </select>
+
+    <select id="releaseCheck" resultMap="BsFormulaChildInfoResult" parameterType="BsFormulaChildInfo">
+        SELECT
+            *
+        FROM
+            bs_formula_child_info
+        WHERE
+            NOT results = 'OK'
+          AND product_code = #{productCode}
+          AND processes_code = #{processesCode};
+    </select>
+
+    <update id="workpieceRelease" parameterType="BsFormulaChildInfo">
+        UPDATE bs_formula_child_info
+        SET results = ''
+        WHERE
+            product_code = #{productCode}
+          AND processes_code = #{processesCode};
+    </update>
+</mapper>
\ No newline at end of file
diff --git a/jcdm-main/src/main/resources/mapper/bs/lineInfo/BsLineInfoMapper.xml b/jcdm-main/src/main/resources/mapper/bs/lineInfo/BsLineInfoMapper.xml
new file mode 100644
index 0000000..4cff440
--- /dev/null
+++ b/jcdm-main/src/main/resources/mapper/bs/lineInfo/BsLineInfoMapper.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.main.bs.lineInfo.mapper.BsLineInfoMapper">
+
+    <resultMap type="BsLineInfo" id="BsLineInfoResult">
+        <result property="id"    column="id"    />
+        <result property="lineCode"    column="line_code"    />
+        <result property="lineName"    column="line_name"    />
+        <result property="workshopCode"    column="workshop_code"    />
+        <result property="workCalendar"    column="work_calendar"    />
+        <result property="spareField1"    column="spare_field_1"    />
+        <result property="spareField2"    column="spare_field_2"    />
+        <result property="remarks"    column="remarks"    />
+        <result property="createUser"    column="create_user"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateUser"    column="update_user"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="workshopName"    column="workshop_name"    />
+        <result property="status"    column="status"    />
+    </resultMap>
+
+    <sql id="selectBsLineInfoVo">
+        select id, line_code, line_name, workshop_code, work_calendar, spare_field_1, spare_field_2, remarks, create_user, create_time, update_user, update_time,workshop_name,status from bs_line_info
+    </sql>
+
+    <select id="selectBsLineInfoList" parameterType="BsLineInfo" resultMap="BsLineInfoResult">
+        <include refid="selectBsLineInfoVo"/>
+        <where>  
+            <if test="lineCode != null  and lineCode != ''"> and line_code like concat('%', #{lineCode}, '%')</if>
+            <if test="lineName != null  and lineName != ''"> and line_name like concat('%', #{lineName}, '%')</if>
+            <if test="workshopCode != null  and workshopCode != ''"> and workshop_code like concat('%', #{workshopCode}, '%')</if>
+            <if test="workCalendar != null  and workCalendar != ''"> and work_calendar = #{workCalendar}</if>
+        </where>
+    </select>
+    
+    <select id="selectBsLineInfoById" parameterType="Long" resultMap="BsLineInfoResult">
+        <include refid="selectBsLineInfoVo"/>
+        where id = #{id}
+    </select>
+        
+    <insert id="insertBsLineInfo" parameterType="BsLineInfo" useGeneratedKeys="true" keyProperty="id">
+        insert into bs_line_info
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="lineCode != null and lineCode != ''">line_code,</if>
+            <if test="lineName != null and lineName != ''">line_name,</if>
+            <if test="workshopCode != null and workshopCode != ''">workshop_code,</if>
+            <if test="workCalendar != null">work_calendar,</if>
+            <if test="spareField1 != null">spare_field_1,</if>
+            <if test="spareField2 != null">spare_field_2,</if>
+            <if test="remarks != null">remarks,</if>
+            <if test="createUser != null">create_user,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateUser != null">update_user,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="workshopName != null">workshop_name,</if>
+            <if test="status != null">status,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="lineCode != null and lineCode != ''">#{lineCode},</if>
+            <if test="lineName != null and lineName != ''">#{lineName},</if>
+            <if test="workshopCode != null and workshopCode != ''">#{workshopCode},</if>
+            <if test="workCalendar != null">#{workCalendar},</if>
+            <if test="spareField1 != null">#{spareField1},</if>
+            <if test="spareField2 != null">#{spareField2},</if>
+            <if test="remarks != null">#{remarks},</if>
+            <if test="createUser != null">#{createUser},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateUser != null">#{updateUser},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="workshopName != null">#{workshopName},</if>
+            <if test="status != null">#{status},</if>
+         </trim>
+    </insert>
+
+    <update id="updateBsLineInfo" parameterType="BsLineInfo">
+        update bs_line_info
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="lineCode != null and lineCode != ''">line_code = #{lineCode},</if>
+            <if test="lineName != null and lineName != ''">line_name = #{lineName},</if>
+            <if test="workshopCode != null and workshopCode != ''">workshop_code = #{workshopCode},</if>
+            <if test="workCalendar != null">work_calendar = #{workCalendar},</if>
+            <if test="spareField1 != null">spare_field_1 = #{spareField1},</if>
+            <if test="spareField2 != null">spare_field_2 = #{spareField2},</if>
+            <if test="remarks != null">remarks = #{remarks},</if>
+            <if test="createUser != null">create_user = #{createUser},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateUser != null">update_user = #{updateUser},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="workshopName != null">workshop_name = #{workshopName},</if>
+            <if test="status != null">status = #{status},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteBsLineInfoById" parameterType="Long">
+        delete from bs_line_info where id = #{id}
+    </delete>
+
+    <delete id="deleteBsLineInfoByIds" parameterType="String">
+        delete from bs_line_info where id in 
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>
\ No newline at end of file
diff --git a/jcdm-main/src/main/resources/mapper/bs/material/BsMaterialInfoMapper.xml b/jcdm-main/src/main/resources/mapper/bs/material/BsMaterialInfoMapper.xml
new file mode 100644
index 0000000..cae981e
--- /dev/null
+++ b/jcdm-main/src/main/resources/mapper/bs/material/BsMaterialInfoMapper.xml
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.main.bs.material.mapper.BsMaterialInfoMapper">
+    <resultMap type="BsMaterialInfo" id="BsMaterialInfoResult">
+        <result property="id"    column="id"    />
+        <result property="materialCode"    column="material_code"    />
+        <result property="materialName"    column="material_name"    />
+        <result property="materialView"    column="material_view"    />
+        <result property="typeZ"    column="type_z"    />
+        <result property="typeL"    column="type_l"    />
+        <result property="unit"    column="unit"    />
+        <result property="matterVersion"    column="matter_version"    />
+        <result property="remarks"    column="remarks"    />
+        <result property="createUser"    column="create_user"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateUser"    column="update_user"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="erpSpec"    column="erp_spec"    />
+        <result property="dataSource"    column="data_source"    />
+        <result property="version"    column="version"    />
+        <result property="status"    column="status"    />
+        <result property="supplier"    column="supplier"    />
+    </resultMap>
+
+    <sql id="selectBsMaterialInfoVo">
+        select id, material_code, material_name, material_view, type_z, type_l, unit, matter_version, remarks, create_user, create_time, update_user, update_time, erp_spec, data_source, version, status, supplier from bs_material_info
+    </sql>
+
+    <select id="selectBsMaterialInfoList" parameterType="BsMaterialInfo" resultMap="BsMaterialInfoResult">
+        <include refid="selectBsMaterialInfoVo"/>
+        <where>  
+            <if test="materialCode != null  and materialCode != ''"> and material_code like concat('%', #{materialCode}, '%')</if>
+            <if test="materialName != null  and materialName != ''"> and material_name like concat('%', #{materialName}, '%')</if>
+            <if test="materialView != null  and materialView != ''"> and material_view = #{materialView}</if>
+            <if test="typeZ != null  and typeZ != ''"> and type_z = #{typeZ}</if>
+            <if test="typeL != null  and typeL != ''"> and type_l = #{typeL}</if>
+            <if test="unit != null  and unit != ''"> and unit = #{unit}</if>
+            <if test="matterVersion != null  and matterVersion != ''"> and matter_version = #{matterVersion}</if>
+            <if test="remarks != null  and remarks != ''"> and remarks = #{remarks}</if>
+            <if test="createUser != null  and createUser != ''"> and create_user = #{createUser}</if>
+            <if test="createTime != null "> and create_time = #{createTime}</if>
+            <if test="updateUser != null  and updateUser != ''"> and update_user = #{updateUser}</if>
+            <if test="erpSpec != null  and erpSpec != ''"> and erp_spec = #{erpSpec}</if>
+            <if test="dataSource != null  and dataSource != ''"> and data_source = #{dataSource}</if>
+            <if test="version != null  and version != ''"> and version = #{version}</if>
+            <if test="status != null  and status != ''"> and status = #{status}</if>
+            <if test="supplier != null  and supplier != ''"> and supplier = #{supplier}</if>
+        </where>
+    </select>
+    
+    <select id="selectBsMaterialInfoById" parameterType="Long" resultMap="BsMaterialInfoResult">
+        <include refid="selectBsMaterialInfoVo"/>
+        where id = #{id}
+    </select>
+        
+    <insert id="insertBsMaterialInfo" parameterType="BsMaterialInfo">
+        insert into bs_material_info
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="id != null">id,</if>
+            <if test="materialCode != null">material_code,</if>
+            <if test="materialName != null">material_name,</if>
+            <if test="materialView != null">material_view,</if>
+            <if test="typeZ != null">type_z,</if>
+            <if test="typeL != null">type_l,</if>
+            <if test="unit != null">unit,</if>
+            <if test="matterVersion != null">matter_version,</if>
+            <if test="remarks != null">remarks,</if>
+            <if test="createUser != null">create_user,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateUser != null">update_user,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="erpSpec != null">erp_spec,</if>
+            <if test="dataSource != null">data_source,</if>
+            <if test="version != null">version,</if>
+            <if test="status != null">status,</if>
+            <if test="supplier != null">supplier,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="id != null">#{id},</if>
+            <if test="materialCode != null">#{materialCode},</if>
+            <if test="materialName != null">#{materialName},</if>
+            <if test="materialView != null">#{materialView},</if>
+            <if test="typeZ != null">#{typeZ},</if>
+            <if test="typeL != null">#{typeL},</if>
+            <if test="unit != null">#{unit},</if>
+            <if test="matterVersion != null">#{matterVersion},</if>
+            <if test="remarks != null">#{remarks},</if>
+            <if test="createUser != null">#{createUser},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateUser != null">#{updateUser},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="erpSpec != null">#{erpSpec},</if>
+            <if test="dataSource != null">#{dataSource},</if>
+            <if test="version != null">#{version},</if>
+            <if test="status != null">#{status},</if>
+            <if test="supplier != null">#{supplier},</if>
+         </trim>
+    </insert>
+
+    <update id="updateBsMaterialInfo" parameterType="BsMaterialInfo">
+        update bs_material_info
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="materialCode != null">material_code = #{materialCode},</if>
+            <if test="materialName != null">material_name = #{materialName},</if>
+            <if test="materialView != null">material_view = #{materialView},</if>
+            <if test="typeZ != null">type_z = #{typeZ},</if>
+            <if test="typeL != null">type_l = #{typeL},</if>
+            <if test="unit != null">unit = #{unit},</if>
+            <if test="matterVersion != null">matter_version = #{matterVersion},</if>
+            <if test="remarks != null">remarks = #{remarks},</if>
+            <if test="createUser != null">create_user = #{createUser},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateUser != null">update_user = #{updateUser},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="erpSpec != null">erp_spec = #{erpSpec},</if>
+            <if test="dataSource != null">data_source = #{dataSource},</if>
+            <if test="version != null">version = #{version},</if>
+            <if test="status != null">status = #{status},</if>
+            <if test="supplier != null">supplier = #{supplier},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteBsMaterialInfoById" parameterType="Long">
+        delete from bs_material_info where id = #{id}
+    </delete>
+
+    <delete id="deleteBsMaterialInfoByIds" parameterType="String">
+        delete from bs_material_info where id in 
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>
\ No newline at end of file
diff --git a/jcdm-main/src/main/resources/mapper/bs/processFile/BsProcessFileMapper.xml b/jcdm-main/src/main/resources/mapper/bs/processFile/BsProcessFileMapper.xml
new file mode 100644
index 0000000..b63bbf9
--- /dev/null
+++ b/jcdm-main/src/main/resources/mapper/bs/processFile/BsProcessFileMapper.xml
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.main.bs.processFile.mapper.BsProcessFileMapper">
+    
+    <resultMap type="BsProcessFile" id="BsProcessFileResult">
+        <result property="id"    column="id"    />
+        <result property="productCode"    column="product_code"    />
+        <result property="productName"    column="product_name"    />
+        <result property="processesCode"    column="processes_code"    />
+        <result property="processesName"    column="processes_name"    />
+        <result property="fileCode"    column="file_code"    />
+        <result property="fileName"    column="file_name"    />
+        <result property="fileAddress"    column="file_address"    />
+        <result property="status"    column="status"    />
+        <result property="createUser"    column="create_user"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateUser"    column="update_user"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="spareField1"    column="spare_field_1"    />
+        <result property="spareField2"    column="spare_field_2"    />
+        <result property="spareField3"    column="spare_field_3"    />
+        <result property="spareField4"    column="spare_field_4"    />
+        <result property="remarks"    column="remarks"    />
+    </resultMap>
+
+    <sql id="selectBsProcessFileVo">
+        select id, product_code, product_name, processes_code, processes_name, file_code, file_name, file_address, status, create_user, create_time, update_user, update_time, spare_field_1, spare_field_2, spare_field_3, spare_field_4, remarks from bs_process_file
+    </sql>
+
+    <select id="selectBsProcessFileList" parameterType="BsProcessFile" resultMap="BsProcessFileResult">
+        <include refid="selectBsProcessFileVo"/>
+        <where>  
+            <if test="productCode != null  and productCode != ''"> and product_code = #{productCode}</if>
+            <if test="productName != null  and productName != ''"> and product_name like concat('%', #{productName}, '%')</if>
+            <if test="processesCode != null  and processesCode != ''"> and processes_code = #{processesCode}</if>
+            <if test="processesName != null  and processesName != ''"> and processes_name like concat('%', #{processesName}, '%')</if>
+            <if test="fileCode != null  and fileCode != ''"> and file_code = #{fileCode}</if>
+            <if test="fileName != null  and fileName != ''"> and file_name like concat('%', #{fileName}, '%')</if>
+            <if test="fileAddress != null  and fileAddress != ''"> and file_address = #{fileAddress}</if>
+            <if test="status != null  and status != ''"> and status = #{status}</if>
+            <if test="createUser != null  and createUser != ''"> and create_user = #{createUser}</if>
+            <if test="updateUser != null  and updateUser != ''"> and update_user = #{updateUser}</if>
+            <if test="remarks != null  and remarks != ''"> and remarks = #{remarks}</if>
+        </where>
+    </select>
+    
+    <select id="selectBsProcessFileById" parameterType="Long" resultMap="BsProcessFileResult">
+        <include refid="selectBsProcessFileVo"/>
+        where id = #{id}
+    </select>
+        
+    <insert id="insertBsProcessFile" parameterType="BsProcessFile" useGeneratedKeys="true" keyProperty="id">
+        insert into bs_process_file
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="productCode != null">product_code,</if>
+            <if test="productName != null">product_name,</if>
+            <if test="processesCode != null">processes_code,</if>
+            <if test="processesName != null">processes_name,</if>
+            <if test="fileCode != null">file_code,</if>
+            <if test="fileName != null">file_name,</if>
+            <if test="fileAddress != null">file_address,</if>
+            <if test="status != null">status,</if>
+            <if test="createUser != null">create_user,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateUser != null">update_user,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="spareField1 != null">spare_field_1,</if>
+            <if test="spareField2 != null">spare_field_2,</if>
+            <if test="spareField3 != null">spare_field_3,</if>
+            <if test="spareField4 != null">spare_field_4,</if>
+            <if test="remarks != null">remarks,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="productCode != null">#{productCode},</if>
+            <if test="productName != null">#{productName},</if>
+            <if test="processesCode != null">#{processesCode},</if>
+            <if test="processesName != null">#{processesName},</if>
+            <if test="fileCode != null">#{fileCode},</if>
+            <if test="fileName != null">#{fileName},</if>
+            <if test="fileAddress != null">#{fileAddress},</if>
+            <if test="status != null">#{status},</if>
+            <if test="createUser != null">#{createUser},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateUser != null">#{updateUser},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="spareField1 != null">#{spareField1},</if>
+            <if test="spareField2 != null">#{spareField2},</if>
+            <if test="spareField3 != null">#{spareField3},</if>
+            <if test="spareField4 != null">#{spareField4},</if>
+            <if test="remarks != null">#{remarks},</if>
+         </trim>
+    </insert>
+
+    <update id="updateBsProcessFile" parameterType="BsProcessFile">
+        update bs_process_file
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="productCode != null">product_code = #{productCode},</if>
+            <if test="productName != null">product_name = #{productName},</if>
+            <if test="processesCode != null">processes_code = #{processesCode},</if>
+            <if test="processesName != null">processes_name = #{processesName},</if>
+            <if test="fileCode != null">file_code = #{fileCode},</if>
+            <if test="fileName != null">file_name = #{fileName},</if>
+            <if test="fileAddress != null">file_address = #{fileAddress},</if>
+            <if test="status != null">status = #{status},</if>
+            <if test="createUser != null">create_user = #{createUser},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateUser != null">update_user = #{updateUser},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="spareField1 != null">spare_field_1 = #{spareField1},</if>
+            <if test="spareField2 != null">spare_field_2 = #{spareField2},</if>
+            <if test="spareField3 != null">spare_field_3 = #{spareField3},</if>
+            <if test="spareField4 != null">spare_field_4 = #{spareField4},</if>
+            <if test="remarks != null">remarks = #{remarks},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteBsProcessFileById" parameterType="Long">
+        delete from bs_process_file where id = #{id}
+    </delete>
+
+    <delete id="deleteBsProcessFileByIds" parameterType="String">
+        delete from bs_process_file where id in 
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>
\ No newline at end of file
diff --git a/jcdm-main/src/main/resources/mapper/bs/processes/BsProcessesInfoMapper.xml b/jcdm-main/src/main/resources/mapper/bs/processes/BsProcessesInfoMapper.xml
new file mode 100644
index 0000000..3245a3f
--- /dev/null
+++ b/jcdm-main/src/main/resources/mapper/bs/processes/BsProcessesInfoMapper.xml
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.main.bs.processes.mapper.BsProcessesInfoMapper">
+    
+    <resultMap type="BsProcessesInfo" id="BsProcessesInfoResult">
+        <result property="id"    column="id"    />
+        <result property="processesCode"    column="processes_code"    />
+        <result property="processesName"    column="processes_name"    />
+        <result property="processesType"    column="processes_type"    />
+        <result property="preparationTime"    column="preparation_time"    />
+        <result property="productiveTime"    column="productive_time"    />
+        <result property="status"    column="status"    />
+        <result property="spareField1"    column="spare_field_1"    />
+        <result property="spareField2"    column="spare_field_2"    />
+        <result property="spareField3"    column="spare_field_3"    />
+        <result property="spareField4"    column="spare_field_4"    />
+        <result property="createUser"    column="create_user"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateUser"    column="update_user"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="remarks"    column="remarks"    />
+    </resultMap>
+
+    <sql id="selectBsProcessesInfoVo">
+        select id, processes_code, processes_name, processes_type, preparation_time, productive_time, status, spare_field_1, spare_field_2, spare_field_3, spare_field_4, create_user, create_time, update_user, update_time, remarks from bs_processes_info
+    </sql>
+
+    <select id="selectBsProcessesInfoList" parameterType="BsProcessesInfo" resultMap="BsProcessesInfoResult">
+        <include refid="selectBsProcessesInfoVo"/>
+        <where>
+            <if test="processesCode != null  and processesCode != ''"> and processes_code = #{processesCode}</if>
+            <if test="processesName != null  and processesName != ''"> and processes_name like concat('%', #{processesName}, '%')</if>
+            <if test="processesType != null  and processesType != ''"> and processes_type like concat('%', #{processesType}, '%')</if>
+            <if test="status != null  and status != ''"> and status = #{status}</if>
+        </where>
+    </select>
+    
+    <select id="selectBsProcessesInfoById" parameterType="Long" resultMap="BsProcessesInfoResult">
+        <include refid="selectBsProcessesInfoVo"/>
+        where id = #{id}
+    </select>
+        
+    <insert id="insertBsProcessesInfo" parameterType="BsProcessesInfo">
+        insert into bs_processes_info
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="id != null">id,</if>
+            <if test="processesCode != null and processesCode != ''">processes_code,</if>
+            <if test="processesName != null">processes_name,</if>
+            <if test="processesType != null and processesType != ''">processes_type,</if>
+            <if test="preparationTime != null">preparation_time,</if>
+            <if test="productiveTime != null">productive_time,</if>
+            <if test="status != null">status,</if>
+            <if test="spareField1 != null">spare_field_1,</if>
+            <if test="spareField2 != null">spare_field_2,</if>
+            <if test="spareField3 != null">spare_field_3,</if>
+            <if test="spareField4 != null">spare_field_4,</if>
+            <if test="createUser != null">create_user,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateUser != null">update_user,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="remarks != null">remarks,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="id != null">#{id},</if>
+            <if test="processesCode != null and processesCode != ''">#{processesCode},</if>
+            <if test="processesName != null">#{processesName},</if>
+            <if test="processesType != null and processesType != ''">#{processesType},</if>
+            <if test="preparationTime != null">#{preparationTime},</if>
+            <if test="productiveTime != null">#{productiveTime},</if>
+            <if test="status != null">#{status},</if>
+            <if test="spareField1 != null">#{spareField1},</if>
+            <if test="spareField2 != null">#{spareField2},</if>
+            <if test="spareField3 != null">#{spareField3},</if>
+            <if test="spareField4 != null">#{spareField4},</if>
+            <if test="createUser != null">#{createUser},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateUser != null">#{updateUser},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="remarks != null">#{remarks},</if>
+         </trim>
+    </insert>
+
+    <update id="updateBsProcessesInfo" parameterType="BsProcessesInfo">
+        update bs_processes_info
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="processesCode != null and processesCode != ''">processes_code = #{processesCode},</if>
+            <if test="processesName != null">processes_name = #{processesName},</if>
+            <if test="processesType != null and processesType != ''">processes_type = #{processesType},</if>
+            <if test="preparationTime != null">preparation_time = #{preparationTime},</if>
+            <if test="productiveTime != null">productive_time = #{productiveTime},</if>
+            <if test="status != null">status = #{status},</if>
+            <if test="spareField1 != null">spare_field_1 = #{spareField1},</if>
+            <if test="spareField2 != null">spare_field_2 = #{spareField2},</if>
+            <if test="spareField3 != null">spare_field_3 = #{spareField3},</if>
+            <if test="spareField4 != null">spare_field_4 = #{spareField4},</if>
+            <if test="createUser != null">create_user = #{createUser},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateUser != null">update_user = #{updateUser},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="remarks != null">remarks = #{remarks},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteBsProcessesInfoById" parameterType="Long">
+        delete from bs_processes_info where id = #{id}
+    </delete>
+
+    <delete id="deleteBsProcessesInfoByIds" parameterType="String">
+        delete from bs_processes_info where id in 
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>
\ No newline at end of file
diff --git a/jcdm-main/src/main/resources/mapper/bs/productBom/BsProductBomInfoMapper.xml b/jcdm-main/src/main/resources/mapper/bs/productBom/BsProductBomInfoMapper.xml
new file mode 100644
index 0000000..d600e4e
--- /dev/null
+++ b/jcdm-main/src/main/resources/mapper/bs/productBom/BsProductBomInfoMapper.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.main.bs.productBom.mapper.BsProductBomInfoMapper">
+    
+    <resultMap type="BsProductBomInfo" id="BsProductBomInfoResult">
+        <result property="id"    column="id"    />
+        <result property="bomCode"    column="bom_code"    />
+        <result property="bomName"    column="bom_name"    />
+        <result property="productCode"    column="product_code"    />
+        <result property="productName"    column="product_name"    />
+        <result property="version"    column="version"    />
+        <result property="status"    column="status"    />
+        <result property="spareField1"    column="spare_field_1"    />
+        <result property="spareField2"    column="spare_field_2"    />
+        <result property="remark"    column="remark"    />
+        <result property="createUser"    column="create_user"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateUser"    column="update_user"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="dataSource"    column="data_source"    />
+    </resultMap>
+
+    <sql id="selectBsProductBomInfoVo">
+        select id, bom_code, bom_name, product_code, product_name, version, status, spare_field_1, spare_field_2, remark, create_user, create_time, update_user, update_time, data_source from bs_product_bom_info
+    </sql>
+
+    <select id="selectBsProductBomInfoList" parameterType="BsProductBomInfo" resultMap="BsProductBomInfoResult">
+        <include refid="selectBsProductBomInfoVo"/>
+        <where>  
+            <if test="bomCode != null  and bomCode != ''"> and bom_code = #{bomCode}</if>
+            <if test="bomName != null  and bomName != ''"> and bom_name like concat('%', #{bomName}, '%')</if>
+            <if test="productCode != null  and productCode != ''"> and product_code = #{productCode}</if>
+            <if test="productName != null  and productName != ''"> and product_name like concat('%', #{productName}, '%')</if>
+            <if test="dataSource != null  and dataSource != ''"> and data_source = #{dataSource}</if>
+        </where>
+    </select>
+    
+    <select id="selectBsProductBomInfoById" parameterType="Long" resultMap="BsProductBomInfoResult">
+        <include refid="selectBsProductBomInfoVo"/>
+        where id = #{id}
+    </select>
+        
+    <insert id="insertBsProductBomInfo" parameterType="BsProductBomInfo">
+        insert into bs_product_bom_info
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="id != null">id,</if>
+            <if test="bomCode != null and bomCode != ''">bom_code,</if>
+            <if test="bomName != null">bom_name,</if>
+            <if test="productCode != null and productCode != ''">product_code,</if>
+            <if test="productName != null">product_name,</if>
+            <if test="version != null">version,</if>
+            <if test="status != null and status != ''">status,</if>
+            <if test="spareField1 != null">spare_field_1,</if>
+            <if test="spareField2 != null">spare_field_2,</if>
+            <if test="remark != null">remark,</if>
+            <if test="createUser != null">create_user,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateUser != null">update_user,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="dataSource != null">data_source,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="id != null">#{id},</if>
+            <if test="bomCode != null and bomCode != ''">#{bomCode},</if>
+            <if test="bomName != null">#{bomName},</if>
+            <if test="productCode != null and productCode != ''">#{productCode},</if>
+            <if test="productName != null">#{productName},</if>
+            <if test="version != null">#{version},</if>
+            <if test="status != null and status != ''">#{status},</if>
+            <if test="spareField1 != null">#{spareField1},</if>
+            <if test="spareField2 != null">#{spareField2},</if>
+            <if test="remark != null">#{remark},</if>
+            <if test="createUser != null">#{createUser},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateUser != null">#{updateUser},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="dataSource != null">#{dataSource},</if>
+         </trim>
+    </insert>
+
+    <update id="updateBsProductBomInfo" parameterType="BsProductBomInfo">
+        update bs_product_bom_info
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="bomCode != null and bomCode != ''">bom_code = #{bomCode},</if>
+            <if test="bomName != null">bom_name = #{bomName},</if>
+            <if test="productCode != null and productCode != ''">product_code = #{productCode},</if>
+            <if test="productName != null">product_name = #{productName},</if>
+            <if test="version != null">version = #{version},</if>
+            <if test="status != null and status != ''">status = #{status},</if>
+            <if test="spareField1 != null">spare_field_1 = #{spareField1},</if>
+            <if test="spareField2 != null">spare_field_2 = #{spareField2},</if>
+            <if test="remark != null">remark = #{remark},</if>
+            <if test="createUser != null">create_user = #{createUser},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateUser != null">update_user = #{updateUser},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="dataSource != null">data_source = #{dataSource},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteBsProductBomInfoById" parameterType="Long">
+        delete from bs_product_bom_info where id = #{id}
+    </delete>
+
+    <delete id="deleteBsProductBomInfoByIds" parameterType="String">
+        delete from bs_product_bom_info where id in 
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>
\ No newline at end of file
diff --git a/jcdm-main/src/main/resources/mapper/bs/productBomChild/BsProductBomChildInfoMapper.xml b/jcdm-main/src/main/resources/mapper/bs/productBomChild/BsProductBomChildInfoMapper.xml
new file mode 100644
index 0000000..0891b2e
--- /dev/null
+++ b/jcdm-main/src/main/resources/mapper/bs/productBomChild/BsProductBomChildInfoMapper.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.main.bs.productBomChild.mapper.BsProductBomChildInfoMapper">
+    
+    <resultMap type="BsProductBomChildInfo" id="BsProductBomChildInfoResult">
+        <result property="id"    column="id"    />
+        <result property="opCode"    column="op_code"    />
+        <result property="opName"    column="op_name"    />
+        <result property="materialCode"    column="material_code"    />
+        <result property="materialName"    column="material_name"    />
+        <result property="costQty"    column="cost_qty"    />
+        <result property="unit"    column="unit"    />
+        <result property="spareField1"    column="spare_field_1"    />
+        <result property="spareField2"    column="spare_field_2"    />
+        <result property="spareField3"    column="spare_field_3"    />
+        <result property="remark"    column="remark"    />
+        <result property="bomCode"    column="bom_code"    />
+        <result property="bomInfoId"    column="bom_info_id"    />
+    </resultMap>
+
+    <sql id="selectBsProductBomChildInfoVo">
+        select id, op_code, op_name, material_code, material_name, cost_qty, unit, spare_field_1, spare_field_2, spare_field_3, remark, bom_code, bom_info_id from bs_product_bom_child_info
+    </sql>
+
+    <select id="selectBsProductBomChildInfoList" parameterType="BsProductBomChildInfo" resultMap="BsProductBomChildInfoResult">
+        <include refid="selectBsProductBomChildInfoVo"/>
+        <where>  
+            <if test="materialCode != null  and materialCode != ''"> and material_code = #{materialCode}</if>
+            <if test="materialName != null  and materialName != ''"> and material_name = #{materialName}</if>
+            <if test="bomCode != null  and bomCode != ''"> and bom_code = #{bomCode}</if>
+            <if test="opCode != null  and opCode != ''"> and op_code = #{opCode}</if>
+            <if test="opName != null  and opName != ''"> and op_name = #{opName}</if>
+
+        </where>
+    </select>
+    
+    <select id="selectBsProductBomChildInfoById" parameterType="Long" resultMap="BsProductBomChildInfoResult">
+        <include refid="selectBsProductBomChildInfoVo"/>
+        where id = #{id}
+    </select>
+        
+    <insert id="insertBsProductBomChildInfo" parameterType="BsProductBomChildInfo">
+        insert into bs_product_bom_child_info
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="id != null">id,</if>
+            <if test="opCode != null">op_code,</if>
+            <if test="opName != null">op_name,</if>
+            <if test="materialCode != null">material_code,</if>
+            <if test="materialName != null">material_name,</if>
+            <if test="costQty != null and costQty != ''">cost_qty,</if>
+            <if test="unit != null and unit != ''">unit,</if>
+            <if test="spareField1 != null">spare_field_1,</if>
+            <if test="spareField2 != null">spare_field_2,</if>
+            <if test="spareField3 != null">spare_field_3,</if>
+            <if test="remark != null">remark,</if>
+            <if test="bomCode != null and bomCode != ''">bom_code,</if>
+            <if test="bomInfoId != null">bom_info_id,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="id != null">#{id},</if>
+            <if test="opCode != null">#{opCode},</if>
+            <if test="opName != null">#{opName},</if>
+            <if test="materialCode != null">#{materialCode},</if>
+            <if test="materialName != null">#{materialName},</if>
+            <if test="costQty != null and costQty != ''">#{costQty},</if>
+            <if test="unit != null and unit != ''">#{unit},</if>
+            <if test="spareField1 != null">#{spareField1},</if>
+            <if test="spareField2 != null">#{spareField2},</if>
+            <if test="spareField3 != null">#{spareField3},</if>
+            <if test="remark != null">#{remark},</if>
+            <if test="bomCode != null and bomCode != ''">#{bomCode},</if>
+            <if test="bomInfoId != null">#{bomInfoId},</if>
+         </trim>
+    </insert>
+
+    <update id="updateBsProductBomChildInfo" parameterType="BsProductBomChildInfo">
+        update bs_product_bom_child_info
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="opCode != null">op_code = #{opCode},</if>
+            <if test="opName != null">op_name = #{opName},</if>
+            <if test="materialCode != null">material_code = #{materialCode},</if>
+            <if test="materialName != null">material_name = #{materialName},</if>
+            <if test="costQty != null and costQty != ''">cost_qty = #{costQty},</if>
+            <if test="unit != null and unit != ''">unit = #{unit},</if>
+            <if test="spareField1 != null">spare_field_1 = #{spareField1},</if>
+            <if test="spareField2 != null">spare_field_2 = #{spareField2},</if>
+            <if test="spareField3 != null">spare_field_3 = #{spareField3},</if>
+            <if test="remark != null">remark = #{remark},</if>
+            <if test="bomCode != null and bomCode != ''">bom_code = #{bomCode},</if>
+            <if test="bomInfoId != null">bom_info_id = #{bomInfoId},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteBsProductBomChildInfoById" parameterType="Long">
+        delete from bs_product_bom_child_info where id = #{id}
+    </delete>
+
+    <delete id="deleteBsProductBomChildInfoByIds" parameterType="String">
+        delete from bs_product_bom_child_info where id in 
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>
\ No newline at end of file
diff --git a/jcdm-main/src/main/resources/mapper/bs/technologyRoute/BsTechnologyRouteInfoMapper.xml b/jcdm-main/src/main/resources/mapper/bs/technologyRoute/BsTechnologyRouteInfoMapper.xml
new file mode 100644
index 0000000..6dad025
--- /dev/null
+++ b/jcdm-main/src/main/resources/mapper/bs/technologyRoute/BsTechnologyRouteInfoMapper.xml
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.main.bs.technologyRoute.mapper.BsTechnologyRouteInfoMapper">
+    
+    <resultMap type="BsTechnologyRouteInfo" id="BsTechnologyRouteInfoResult">
+        <result property="id"    column="id"    />
+        <result property="routeCode"    column="route_code"    />
+        <result property="routeName"    column="route_name"    />
+        <result property="productCode"    column="product_code"    />
+        <result property="productName"    column="product_name"    />
+        <result property="version"    column="version"    />
+        <result property="status"    column="status"    />
+        <result property="dataSource"    column="data_source"    />
+        <result property="remark"    column="remark"    />
+        <result property="createUser"    column="create_user"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateUser"    column="update_user"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="spareField1"    column="spare_field_1"    />
+        <result property="spareField2"    column="spare_field_2"    />
+        <result property="spareField3"    column="spare_field_3"    />
+        <result property="spareField4"    column="spare_field_4"    />
+    </resultMap>
+
+    <sql id="selectBsTechnologyRouteInfoVo">
+        select id, route_code, route_name, product_code, product_name, version, status, data_source, remark, create_user, create_time, update_user, update_time, spare_field_1, spare_field_2, spare_field_3, spare_field_4 from bs_technology_route_info
+    </sql>
+
+    <select id="selectBsTechnologyRouteInfoList" parameterType="BsTechnologyRouteInfo" resultMap="BsTechnologyRouteInfoResult">
+        <include refid="selectBsTechnologyRouteInfoVo"/>
+        <where>  
+            <if test="routeCode != null  and routeCode != ''"> and route_code like concat('%', #{routeCode}, '%')</if>
+            <if test="routeName != null  and routeName != ''"> and route_name like concat('%', #{routeName}, '%')</if>
+            <if test="productCode != null  and productCode != ''"> and product_code like concat('%', #{productCode}, '%')</if>
+            <if test="productName != null  and productName != ''"> and product_name like concat('%', #{productName}, '%')</if>
+            <if test="status != null  and status != ''"> and status = #{status}</if>
+            <if test="dataSource != null  and dataSource != ''"> and data_source like concat('%', #{dataSource}, '%')</if>
+        </where>
+    </select>
+    
+    <select id="selectBsTechnologyRouteInfoById" parameterType="Long" resultMap="BsTechnologyRouteInfoResult">
+        <include refid="selectBsTechnologyRouteInfoVo"/>
+        where id = #{id}
+    </select>
+        
+    <insert id="insertBsTechnologyRouteInfo" parameterType="BsTechnologyRouteInfo">
+        insert into bs_technology_route_info
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="id != null">id,</if>
+            <if test="routeCode != null and routeCode != ''">route_code,</if>
+            <if test="routeName != null">route_name,</if>
+            <if test="productCode != null and productCode != ''">product_code,</if>
+            <if test="productName != null">product_name,</if>
+            <if test="version != null">version,</if>
+            <if test="status != null">status,</if>
+            <if test="dataSource != null">data_source,</if>
+            <if test="remark != null">remark,</if>
+            <if test="createUser != null">create_user,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateUser != null">update_user,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="spareField1 != null">spare_field_1,</if>
+            <if test="spareField2 != null">spare_field_2,</if>
+            <if test="spareField3 != null">spare_field_3,</if>
+            <if test="spareField4 != null">spare_field_4,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="id != null">#{id},</if>
+            <if test="routeCode != null and routeCode != ''">#{routeCode},</if>
+            <if test="routeName != null">#{routeName},</if>
+            <if test="productCode != null and productCode != ''">#{productCode},</if>
+            <if test="productName != null">#{productName},</if>
+            <if test="version != null">#{version},</if>
+            <if test="status != null">#{status},</if>
+            <if test="dataSource != null">#{dataSource},</if>
+            <if test="remark != null">#{remark},</if>
+            <if test="createUser != null">#{createUser},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateUser != null">#{updateUser},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="spareField1 != null">#{spareField1},</if>
+            <if test="spareField2 != null">#{spareField2},</if>
+            <if test="spareField3 != null">#{spareField3},</if>
+            <if test="spareField4 != null">#{spareField4},</if>
+         </trim>
+    </insert>
+
+    <update id="updateBsTechnologyRouteInfo" parameterType="BsTechnologyRouteInfo">
+        update bs_technology_route_info
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="routeCode != null and routeCode != ''">route_code = #{routeCode},</if>
+            <if test="routeName != null">route_name = #{routeName},</if>
+            <if test="productCode != null and productCode != ''">product_code = #{productCode},</if>
+            <if test="productName != null">product_name = #{productName},</if>
+            <if test="version != null">version = #{version},</if>
+            <if test="status != null">status = #{status},</if>
+            <if test="dataSource != null">data_source = #{dataSource},</if>
+            <if test="remark != null">remark = #{remark},</if>
+            <if test="createUser != null">create_user = #{createUser},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateUser != null">update_user = #{updateUser},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="spareField1 != null">spare_field_1 = #{spareField1},</if>
+            <if test="spareField2 != null">spare_field_2 = #{spareField2},</if>
+            <if test="spareField3 != null">spare_field_3 = #{spareField3},</if>
+            <if test="spareField4 != null">spare_field_4 = #{spareField4},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteBsTechnologyRouteInfoById" parameterType="Long">
+        delete from bs_technology_route_info where id = #{id}
+    </delete>
+
+    <delete id="deleteBsTechnologyRouteInfoByIds" parameterType="String">
+        delete from bs_technology_route_info where id in 
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>
\ No newline at end of file
diff --git a/jcdm-main/src/main/resources/mapper/bs/technologyRouteChild/BsTechnologyRouteChildInfoMapper.xml b/jcdm-main/src/main/resources/mapper/bs/technologyRouteChild/BsTechnologyRouteChildInfoMapper.xml
new file mode 100644
index 0000000..f7e46c9
--- /dev/null
+++ b/jcdm-main/src/main/resources/mapper/bs/technologyRouteChild/BsTechnologyRouteChildInfoMapper.xml
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.main.bs.mapper.BsTechnologyRouteChildInfoMapper">
+    
+    <resultMap type="BsTechnologyRouteChildInfo" id="BsTechnologyRouteChildInfoResult">
+        <result property="id"    column="id"    />
+        <result property="processesCode"    column="processes_code"    />
+        <result property="processesName"    column="processes_name"    />
+        <result property="stepNo"    column="step_no"    />
+        <result property="nextProcess"    column="next_process"    />
+        <result property="nextProcessBond"    column="next_process_bond"    />
+        <result property="keyProcessesFlag"    column="key_processes_flag"    />
+        <result property="preparationTime"    column="preparation_time"    />
+        <result property="waitTime"    column="wait_time"    />
+        <result property="createUser"    column="create_user"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateUser"    column="update_user"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="remark"    column="remark"    />
+        <result property="routeCode"    column="route_code"    />
+        <result property="spareField1"    column="spare_field_1"    />
+        <result property="spareField2"    column="spare_field_2"    />
+        <result property="spareField3"    column="spare_field_3"    />
+        <result property="spareField4"    column="spare_field_4"    />
+        <result property="routeId"    column="route_id"    />
+
+    </resultMap>
+
+    <sql id="selectBsTechnologyRouteChildInfoVo">
+        select route_id, id, processes_code, processes_name, step_no, next_process, next_process_bond, key_processes_flag, preparation_time, wait_time, create_user, create_time, update_user, update_time, remark, route_code, spare_field_1, spare_field_2, spare_field_3, spare_field_4 from bs_technology_route_child_info
+    </sql>
+
+    <select id="selectBsTechnologyRouteChildInfoList" parameterType="BsTechnologyRouteChildInfo" resultMap="BsTechnologyRouteChildInfoResult">
+        <include refid="selectBsTechnologyRouteChildInfoVo"/>
+        <where>  
+            <if test="processesCode != null  and processesCode != ''"> and processes_code like concat('%', #{processesCode}, '%')</if>
+            <if test="processesName != null  and processesName != ''"> and processes_name like concat('%', #{processesName}, '%')</if>
+            <if test="keyProcessesFlag != null  and keyProcessesFlag != ''"> and key_processes_flag = #{keyProcessesFlag}</if>
+            <if test="routeCode != null  and routeCode != ''"> and route_code = #{routeCode}</if>
+            <if test="routeId != null  and routeId != ''"> and route_Id = #{routeId}</if>
+
+        </where>
+    </select>
+    
+    <select id="selectBsTechnologyRouteChildInfoById" parameterType="Long" resultMap="BsTechnologyRouteChildInfoResult">
+        <include refid="selectBsTechnologyRouteChildInfoVo"/>
+        where id = #{id}
+    </select>
+        
+    <insert id="insertBsTechnologyRouteChildInfo" parameterType="BsTechnologyRouteChildInfo">
+        insert into bs_technology_route_child_info
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="id != null">id,</if>
+            <if test="processesCode != null and processesCode != ''">processes_code,</if>
+            <if test="processesName != null">processes_name,</if>
+            <if test="stepNo != null">step_no,</if>
+            <if test="nextProcess != null">next_process,</if>
+            <if test="nextProcessBond != null">next_process_bond,</if>
+            <if test="keyProcessesFlag != null">key_processes_flag,</if>
+            <if test="preparationTime != null">preparation_time,</if>
+            <if test="waitTime != null">wait_time,</if>
+            <if test="createUser != null">create_user,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateUser != null">update_user,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="remark != null">remark,</if>
+            <if test="routeCode != null">route_code,</if>
+            <if test="spareField1 != null">spare_field_1,</if>
+            <if test="spareField2 != null">spare_field_2,</if>
+            <if test="spareField3 != null">spare_field_3,</if>
+            <if test="spareField4 != null">spare_field_4,</if>
+            <if test="routeId != null">route_id,</if>
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="id != null">#{id},</if>
+            <if test="processesCode != null and processesCode != ''">#{processesCode},</if>
+            <if test="processesName != null">#{processesName},</if>
+            <if test="stepNo != null">#{stepNo},</if>
+            <if test="nextProcess != null">#{nextProcess},</if>
+            <if test="nextProcessBond != null">#{nextProcessBond},</if>
+            <if test="keyProcessesFlag != null">#{keyProcessesFlag},</if>
+            <if test="preparationTime != null">#{preparationTime},</if>
+            <if test="waitTime != null">#{waitTime},</if>
+            <if test="createUser != null">#{createUser},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateUser != null">#{updateUser},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="remark != null">#{remark},</if>
+            <if test="routeCode != null">#{routeCode},</if>
+            <if test="spareField1 != null">#{spareField1},</if>
+            <if test="spareField2 != null">#{spareField2},</if>
+            <if test="spareField3 != null">#{spareField3},</if>
+            <if test="spareField4 != null">#{spareField4},</if>
+            <if test="routeId != null">#{routeId},</if>
+        </trim>
+    </insert>
+
+    <update id="updateBsTechnologyRouteChildInfo" parameterType="BsTechnologyRouteChildInfo">
+        update bs_technology_route_child_info
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="processesCode != null and processesCode != ''">processes_code = #{processesCode},</if>
+            <if test="processesName != null">processes_name = #{processesName},</if>
+            <if test="stepNo != null">step_no = #{stepNo},</if>
+            <if test="nextProcess != null">next_process = #{nextProcess},</if>
+            <if test="nextProcessBond != null">next_process_bond = #{nextProcessBond},</if>
+            <if test="keyProcessesFlag != null">key_processes_flag = #{keyProcessesFlag},</if>
+            <if test="preparationTime != null">preparation_time = #{preparationTime},</if>
+            <if test="waitTime != null">wait_time = #{waitTime},</if>
+            <if test="createUser != null">create_user = #{createUser},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateUser != null">update_user = #{updateUser},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="remark != null">remark = #{remark},</if>
+            <if test="routeCode != null">route_code = #{routeCode},</if>
+            <if test="spareField1 != null">spare_field_1 = #{spareField1},</if>
+            <if test="spareField2 != null">spare_field_2 = #{spareField2},</if>
+            <if test="spareField3 != null">spare_field_3 = #{spareField3},</if>
+            <if test="spareField4 != null">spare_field_4 = #{spareField4},</if>
+            <if test="routeId != null">route_id = #{routeId},</if>
+
+        </trim>
+        where id = #{id}
+    </update>
+
+    <update id="updateBsTechnologyRouteChildByCodeInfo" parameterType="BsTechnologyRouteChildInfo">
+        update bs_technology_route_child_info
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="processesCode != null and processesCode != ''">processes_code = #{processesCode},</if>
+            <if test="processesName != null">processes_name = #{processesName},</if>
+            <if test="stepNo != null">step_no = #{stepNo},</if>
+            <if test="nextProcess != null">next_process = #{nextProcess},</if>
+            <if test="nextProcessBond != null">next_process_bond = #{nextProcessBond},</if>
+            <if test="keyProcessesFlag != null">key_processes_flag = #{keyProcessesFlag},</if>
+            <if test="preparationTime != null">preparation_time = #{preparationTime},</if>
+            <if test="waitTime != null">wait_time = #{waitTime},</if>
+            <if test="createUser != null">create_user = #{createUser},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateUser != null">update_user = #{updateUser},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="remark != null">remark = #{remark},</if>
+            <if test="routeCode != null">route_code = #{routeCode},</if>
+            <if test="spareField1 != null">spare_field_1 = #{spareField1},</if>
+            <if test="spareField2 != null">spare_field_2 = #{spareField2},</if>
+            <if test="spareField3 != null">spare_field_3 = #{spareField3},</if>
+            <if test="spareField4 != null">spare_field_4 = #{spareField4},</if>
+            <if test="routeId != null">route_id = #{routeId},</if>
+
+        </trim>
+        where route_id = #{routeId}
+    </update>
+
+    <delete id="deleteBsTechnologyRouteChildInfoById" parameterType="Long">
+        delete from bs_technology_route_child_info where id = #{id}
+    </delete>
+
+    <delete id="deleteBsTechnologyRouteChildInfoByIds" parameterType="String">
+        delete from bs_technology_route_child_info where id in 
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>
\ No newline at end of file
diff --git a/jcdm-main/src/main/resources/mapper/bs/workshop/BsWorkshopInfoMapper.xml b/jcdm-main/src/main/resources/mapper/bs/workshop/BsWorkshopInfoMapper.xml
new file mode 100644
index 0000000..183d2f7
--- /dev/null
+++ b/jcdm-main/src/main/resources/mapper/bs/workshop/BsWorkshopInfoMapper.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.main.bs.workshop.mapper.BsWorkshopInfoMapper">
+    
+    <resultMap type="BsWorkshopInfo" id="BsWorkshopInfoResult">
+        <result property="id"    column="id"    />
+        <result property="workshopCode"    column="workshop_code"    />
+        <result property="workshopName"    column="workshop_name"    />
+        <result property="spareField1"    column="spare_field_1"    />
+        <result property="spareField2"    column="spare_field_2"    />
+        <result property="remarks"    column="remarks"    />
+        <result property="createUser"    column="create_user"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateUser"    column="update_user"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="status"    column="status"    />
+    </resultMap>
+
+    <sql id="selectBsWorkshopInfoVo">
+        select id, workshop_code, workshop_name, spare_field_1, spare_field_2, remarks, create_user, create_time, update_user, update_time,status from bs_workshop_info
+    </sql>
+
+    <select id="selectBsWorkshopInfoList" parameterType="BsWorkshopInfo" resultMap="BsWorkshopInfoResult">
+        <include refid="selectBsWorkshopInfoVo"/>
+        <where>  
+            <if test="workshopCode != null  and workshopCode != ''"> and workshop_code like concat('%', #{workshopCode}, '%')</if>
+            <if test="workshopName != null  and workshopName != ''"> and workshop_name like concat('%', #{workshopName}, '%')</if>
+            <if test="remarks != null  and remarks != ''"> and remarks like concat('%', #{remarks}, '%')</if>
+            <if test="createUser != null  and createUser != ''"> and create_user like concat('%', #{createUser}, '%')</if>
+        </where>
+    </select>
+    
+    <select id="selectBsWorkshopInfoById" parameterType="Long" resultMap="BsWorkshopInfoResult">
+        <include refid="selectBsWorkshopInfoVo"/>
+        where id = #{id}
+    </select>
+        
+    <insert id="insertBsWorkshopInfo" parameterType="BsWorkshopInfo">
+        insert into bs_workshop_info
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="id != null">id,</if>
+            <if test="workshopCode != null">workshop_code,</if>
+            <if test="workshopName != null">workshop_name,</if>
+            <if test="spareField1 != null">spare_field_1,</if>
+            <if test="spareField2 != null">spare_field_2,</if>
+            <if test="remarks != null">remarks,</if>
+            <if test="createUser != null">create_user,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateUser != null">update_user,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="status != null">status,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="id != null">#{id},</if>
+            <if test="workshopCode != null">#{workshopCode},</if>
+            <if test="workshopName != null">#{workshopName},</if>
+            <if test="spareField1 != null">#{spareField1},</if>
+            <if test="spareField2 != null">#{spareField2},</if>
+            <if test="remarks != null">#{remarks},</if>
+            <if test="createUser != null">#{createUser},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateUser != null">#{updateUser},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="status != null">#{status},</if>
+         </trim>
+    </insert>
+
+    <update id="updateBsWorkshopInfo" parameterType="BsWorkshopInfo">
+        update bs_workshop_info
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="workshopCode != null">workshop_code = #{workshopCode},</if>
+            <if test="workshopName != null">workshop_name = #{workshopName},</if>
+            <if test="spareField1 != null">spare_field_1 = #{spareField1},</if>
+            <if test="spareField2 != null">spare_field_2 = #{spareField2},</if>
+            <if test="remarks != null">remarks = #{remarks},</if>
+            <if test="createUser != null">create_user = #{createUser},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateUser != null">update_user = #{updateUser},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="status != null">status = #{status},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteBsWorkshopInfoById" parameterType="Long">
+        delete from bs_workshop_info where id = #{id}
+    </delete>
+
+    <delete id="deleteBsWorkshopInfoByIds" parameterType="String">
+        delete from bs_workshop_info where id in 
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>
\ No newline at end of file
diff --git a/jcdm-main/src/main/resources/mapper/da/collectionParamConf/DaCollectionParamConfMapper.xml b/jcdm-main/src/main/resources/mapper/da/collectionParamConf/DaCollectionParamConfMapper.xml
new file mode 100644
index 0000000..06e8c13
--- /dev/null
+++ b/jcdm-main/src/main/resources/mapper/da/collectionParamConf/DaCollectionParamConfMapper.xml
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.main.da.collectionParamConf.mapper.DaCollectionParamConfMapper">
+    
+    <resultMap type="DaCollectionParamConf" id="DaCollectionParamConfResult">
+        <result property="id"    column="id"    />
+        <result property="processesCode"    column="processes_code"    />
+        <result property="parameterSetCode"    column="parameter_set_code"    />
+        <result property="parameterSetName"    column="parameter_set_name"    />
+        <result property="collectParameterId"    column="collect_parameter_id"    />
+        <result property="collectParameterName"    column="collect_parameter_name"    />
+        <result property="contrastParameterFlag"    column="contrast_parameter_flag"    />
+        <result property="collectParameterType"    column="collect_parameter_type"    />
+        <result property="collectParameterUnit"    column="collect_parameter_unit"    />
+        <result property="Descriptives"    column="Descriptives"    />
+        <result property="paramUpper"    column="param_upper"    />
+        <result property="paramLower"    column="param_lower"    />
+        <result property="paramCentral"    column="param_Central"    />
+        <result property="productCode"    column="product_code"    />
+        <result property="gatherAddress"    column="gather_address"    />
+        <result property="gatherSequence"    column="gather_sequence"    />
+        <result property="remarks"    column="remarks"    />
+        <result property="createUser"    column="create_user"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateUser"    column="update_user"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="spareField1"    column="spare_field_1"    />
+        <result property="spareField2"    column="spare_field_2"    />
+        <result property="spareField3"    column="spare_field_3"    />
+        <result property="spareField4"    column="spare_field_4"    />
+    </resultMap>
+
+    <sql id="selectDaCollectionParamConfVo">
+        select id, processes_code, parameter_set_code, parameter_set_name, collect_parameter_id, collect_parameter_name, contrast_parameter_flag, collect_parameter_type, collect_parameter_unit, Descriptives, param_upper, param_lower, param_Central, product_code, gather_address, gather_sequence, remarks, create_user, create_time, update_user, update_time, spare_field_1, spare_field_2, spare_field_3, spare_field_4 from da_collection_param_conf
+    </sql>
+
+    <select id="selectDaCollectionParamConfList" parameterType="DaCollectionParamConf" resultMap="DaCollectionParamConfResult">
+        <include refid="selectDaCollectionParamConfVo"/>
+        <where>  
+            <if test="processesCode != null  and processesCode != ''"> and processes_code like concat('%', #{processesCode}, '%')</if>
+            <if test="parameterSetCode != null  and parameterSetCode != ''"> and parameter_set_code like concat('%', #{parameterSetCode}, '%')</if>
+            <if test="parameterSetName != null  and parameterSetName != ''"> and parameter_set_name like concat('%', #{parameterSetName}, '%')</if>
+            <if test="collectParameterId != null  and collectParameterId != ''"> and collect_parameter_id like concat('%', #{collectParameterId}, '%')</if>
+            <if test="collectParameterName != null  and collectParameterName != ''"> and collect_parameter_name like concat('%', #{collectParameterName}, '%')</if>
+            <if test="contrastParameterFlag != null  and contrastParameterFlag != ''"> and contrast_parameter_flag like concat('%', #{contrastParameterFlag}, '%')</if>
+            <if test="collectParameterType != null  and collectParameterType != ''"> and collect_parameter_type like concat('%', #{collectParameterType}, '%')</if>
+            <if test="productCode != null  and productCode != ''"> and product_code like concat('%', #{productCode}, '%')</if>
+        </where>
+    </select>
+    
+    <select id="selectDaCollectionParamConfById" parameterType="Long" resultMap="DaCollectionParamConfResult">
+        <include refid="selectDaCollectionParamConfVo"/>
+        where id = #{id}
+    </select>
+        
+    <insert id="insertDaCollectionParamConf" parameterType="DaCollectionParamConf">
+        insert into da_collection_param_conf
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="id != null">id,</if>
+            <if test="processesCode != null">processes_code,</if>
+            <if test="parameterSetCode != null">parameter_set_code,</if>
+            <if test="parameterSetName != null">parameter_set_name,</if>
+            <if test="collectParameterId != null">collect_parameter_id,</if>
+            <if test="collectParameterName != null">collect_parameter_name,</if>
+            <if test="contrastParameterFlag != null">contrast_parameter_flag,</if>
+            <if test="collectParameterType != null">collect_parameter_type,</if>
+            <if test="collectParameterUnit != null">collect_parameter_unit,</if>
+            <if test="Descriptives != null">Descriptives,</if>
+            <if test="paramUpper != null">param_upper,</if>
+            <if test="paramLower != null">param_lower,</if>
+            <if test="paramCentral != null">param_Central,</if>
+            <if test="productCode != null">product_code,</if>
+            <if test="gatherAddress != null">gather_address,</if>
+            <if test="gatherSequence != null">gather_sequence,</if>
+            <if test="remarks != null">remarks,</if>
+            <if test="createUser != null">create_user,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateUser != null">update_user,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="spareField1 != null">spare_field_1,</if>
+            <if test="spareField2 != null">spare_field_2,</if>
+            <if test="spareField3 != null">spare_field_3,</if>
+            <if test="spareField4 != null">spare_field_4,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="id != null">#{id},</if>
+            <if test="processesCode != null">#{processesCode},</if>
+            <if test="parameterSetCode != null">#{parameterSetCode},</if>
+            <if test="parameterSetName != null">#{parameterSetName},</if>
+            <if test="collectParameterId != null">#{collectParameterId},</if>
+            <if test="collectParameterName != null">#{collectParameterName},</if>
+            <if test="contrastParameterFlag != null">#{contrastParameterFlag},</if>
+            <if test="collectParameterType != null">#{collectParameterType},</if>
+            <if test="collectParameterUnit != null">#{collectParameterUnit},</if>
+            <if test="Descriptives != null">#{Descriptives},</if>
+            <if test="paramUpper != null">#{paramUpper},</if>
+            <if test="paramLower != null">#{paramLower},</if>
+            <if test="paramCentral != null">#{paramCentral},</if>
+            <if test="productCode != null">#{productCode},</if>
+            <if test="gatherAddress != null">#{gatherAddress},</if>
+            <if test="gatherSequence != null">#{gatherSequence},</if>
+            <if test="remarks != null">#{remarks},</if>
+            <if test="createUser != null">#{createUser},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateUser != null">#{updateUser},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="spareField1 != null">#{spareField1},</if>
+            <if test="spareField2 != null">#{spareField2},</if>
+            <if test="spareField3 != null">#{spareField3},</if>
+            <if test="spareField4 != null">#{spareField4},</if>
+         </trim>
+    </insert>
+
+    <update id="updateDaCollectionParamConf" parameterType="DaCollectionParamConf">
+        update da_collection_param_conf
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="processesCode != null">processes_code = #{processesCode},</if>
+            <if test="parameterSetCode != null">parameter_set_code = #{parameterSetCode},</if>
+            <if test="parameterSetName != null">parameter_set_name = #{parameterSetName},</if>
+            <if test="collectParameterId != null">collect_parameter_id = #{collectParameterId},</if>
+            <if test="collectParameterName != null">collect_parameter_name = #{collectParameterName},</if>
+            <if test="contrastParameterFlag != null">contrast_parameter_flag = #{contrastParameterFlag},</if>
+            <if test="collectParameterType != null">collect_parameter_type = #{collectParameterType},</if>
+            <if test="collectParameterUnit != null">collect_parameter_unit = #{collectParameterUnit},</if>
+            <if test="Descriptives != null">Descriptives = #{Descriptives},</if>
+            <if test="paramUpper != null">param_upper = #{paramUpper},</if>
+            <if test="paramLower != null">param_lower = #{paramLower},</if>
+            <if test="paramCentral != null">param_Central = #{paramCentral},</if>
+            <if test="productCode != null">product_code = #{productCode},</if>
+            <if test="gatherAddress != null">gather_address = #{gatherAddress},</if>
+            <if test="gatherSequence != null">gather_sequence = #{gatherSequence},</if>
+            <if test="remarks != null">remarks = #{remarks},</if>
+            <if test="createUser != null">create_user = #{createUser},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateUser != null">update_user = #{updateUser},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="spareField1 != null">spare_field_1 = #{spareField1},</if>
+            <if test="spareField2 != null">spare_field_2 = #{spareField2},</if>
+            <if test="spareField3 != null">spare_field_3 = #{spareField3},</if>
+            <if test="spareField4 != null">spare_field_4 = #{spareField4},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteDaCollectionParamConfById" parameterType="Long">
+        delete from da_collection_param_conf where id = #{id}
+    </delete>
+
+    <delete id="deleteDaCollectionParamConfByIds" parameterType="String">
+        delete from da_collection_param_conf where id in 
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>
\ No newline at end of file
diff --git a/jcdm-main/src/main/resources/mapper/da/opcuaconfig/DaOpcuaConfigMapper.xml b/jcdm-main/src/main/resources/mapper/da/opcuaconfig/DaOpcuaConfigMapper.xml
new file mode 100644
index 0000000..9832bf4
--- /dev/null
+++ b/jcdm-main/src/main/resources/mapper/da/opcuaconfig/DaOpcuaConfigMapper.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.main.da.opcuaconfig.mapper.DaOpcuaConfigMapper">
+    <resultMap type="DaOpcuaConfig" id="DaOpcuaConfigResult">
+        <result property="id"    column="id"    />
+        <result property="node"    column="node"    />
+        <result property="sysTypes"    column="sys_types"    />
+        <result property="subscribe"    column="subscribe"    />
+        <result property="rFunction"    column="r_function"    />
+        <result property="remarks"    column="remarks"    />
+        <result property="processName"    column="process_name"    />
+        <result property="process"    column="process"    />
+        <result property="state"    column="state"    />
+    </resultMap>
+
+    <sql id="selectDaOpcuaConfigVo">
+        select id, node, sys_types, subscribe, r_function, remarks, process_name, process, state from da_opcua_config
+    </sql>
+
+    <select id="selectDaOpcuaConfigList" parameterType="DaOpcuaConfig" resultMap="DaOpcuaConfigResult">
+        <include refid="selectDaOpcuaConfigVo"/>
+        <where>  
+            <if test="node != null  and node != ''"> and node = #{node}</if>
+            <if test="rFunction != null  and rFunction != ''"> and r_function = #{rFunction}</if>
+            <if test="process != null  and process != ''"> and process = #{process}</if>
+            <if test="state != null "> and state = #{state}</if>
+        </where>
+    </select>
+    
+    <select id="selectDaOpcuaConfigById" parameterType="Long" resultMap="DaOpcuaConfigResult">
+        <include refid="selectDaOpcuaConfigVo"/>
+        where id = #{id}
+    </select>
+        
+    <insert id="insertDaOpcuaConfig" parameterType="DaOpcuaConfig" useGeneratedKeys="true" keyProperty="id">
+        insert into da_opcua_config
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="node != null">node,</if>
+            <if test="sysTypes != null">sys_types,</if>
+            <if test="subscribe != null">subscribe,</if>
+            <if test="rFunction != null">r_function,</if>
+            <if test="remarks != null">remarks,</if>
+            <if test="processName != null">process_name,</if>
+            <if test="process != null">process,</if>
+            <if test="state != null">state,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="node != null">#{node},</if>
+            <if test="sysTypes != null">#{sysTypes},</if>
+            <if test="subscribe != null">#{subscribe},</if>
+            <if test="rFunction != null">#{rFunction},</if>
+            <if test="remarks != null">#{remarks},</if>
+            <if test="processName != null">#{processName},</if>
+            <if test="process != null">#{process},</if>
+            <if test="state != null">#{state},</if>
+         </trim>
+    </insert>
+
+    <update id="updateDaOpcuaConfig" parameterType="DaOpcuaConfig">
+        update da_opcua_config
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="node != null">node = #{node},</if>
+            <if test="sysTypes != null">sys_types = #{sysTypes},</if>
+            <if test="subscribe != null">subscribe = #{subscribe},</if>
+            <if test="rFunction != null">r_function = #{rFunction},</if>
+            <if test="remarks != null">remarks = #{remarks},</if>
+            <if test="processName != null">process_name = #{processName},</if>
+            <if test="process != null">process = #{process},</if>
+            <if test="state != null">state = #{state},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteDaOpcuaConfigById" parameterType="Long">
+        delete from da_opcua_config where id = #{id}
+    </delete>
+
+    <delete id="deleteDaOpcuaConfigByIds" parameterType="String">
+        delete from da_opcua_config where id in 
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>
\ No newline at end of file
diff --git a/jcdm-main/src/main/resources/mapper/da/paramCollection/DaParamCollectionMapper.xml b/jcdm-main/src/main/resources/mapper/da/paramCollection/DaParamCollectionMapper.xml
new file mode 100644
index 0000000..f8bfd29
--- /dev/null
+++ b/jcdm-main/src/main/resources/mapper/da/paramCollection/DaParamCollectionMapper.xml
@@ -0,0 +1,149 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.main.da.paramCollection.mapper.DaParamCollectionMapper">
+    
+    <resultMap type="DaParamCollection" id="DaParamCollectionResult">
+        <result property="id"    column="id"    />
+        <result property="workOrderNo"    column="work_order_no"    />
+        <result property="sfcCode"    column="sfc_code"    />
+        <result property="productCode"    column="product_code"    />
+        <result property="productionLine"    column="production_line"    />
+        <result property="locationCode"    column="location_code"    />
+        <result property="equipmentNo"    column="equipment_no"    />
+        <result property="paramCode"    column="param_code"    />
+        <result property="paramValue"    column="param_value"    />
+        <result property="paramUpper"    column="param_upper"    />
+        <result property="paramLower"    column="param_lower"    />
+        <result property="paramStandard"    column="param_standard"    />
+        <result property="collectionTime"    column="collection_time"    />
+        <result property="spareField1"    column="spare_field_1"    />
+        <result property="spareField2"    column="spare_field_2"    />
+        <result property="createUser"    column="create_user"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateUser"    column="update_user"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="state"    column="state"    />
+        <result property="paramName"    column="param_name"    />
+        <result property="unit"    column="unit"    />
+        <result property="type"    column="type"    />
+    </resultMap>
+
+    <sql id="selectDaParamCollectionVo">
+        select id, work_order_no, sfc_code, product_code, production_line, location_code, equipment_no, param_code, param_value, param_upper, param_lower, param_standard, collection_time, spare_field_1, spare_field_2, create_user, create_time, update_user, update_time, state, param_name, unit, type from da_param_collection
+    </sql>
+
+    <select id="selectDaParamCollectionList" parameterType="DaParamCollection" resultMap="DaParamCollectionResult">
+        <include refid="selectDaParamCollectionVo"/>
+        <where>  
+            <if test="workOrderNo != null  and workOrderNo != ''"> and work_order_no = #{workOrderNo}</if>
+            <if test="type != null  and type != ''"> and type = #{type}</if>
+            <if test="sfcCode != null  and sfcCode != ''"> and sfc_code = #{sfcCode}</if>
+            <if test="productCode != null  and productCode != ''"> and product_code = #{productCode}</if>
+            <if test="productionLine != null  and productionLine != ''"> and production_line = #{productionLine}</if>
+            <if test="locationCode != null  and locationCode != ''"> and location_code = #{locationCode}</if>
+            <if test="equipmentNo != null  and equipmentNo != ''"> and equipment_no = #{equipmentNo}</if>
+            <if test="paramCode != null  and paramCode != ''"> and param_code = #{paramCode}</if>
+        </where>
+    </select>
+    
+    <select id="selectDaParamCollectionById" parameterType="Long" resultMap="DaParamCollectionResult">
+        <include refid="selectDaParamCollectionVo"/>
+        where id = #{id}
+    </select>
+        
+    <insert id="insertDaParamCollection" parameterType="DaParamCollection">
+        insert into da_param_collection
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="id != null">id,</if>
+            <if test="workOrderNo != null and workOrderNo != ''">work_order_no,</if>
+            <if test="sfcCode != null and sfcCode != ''">sfc_code,</if>
+            <if test="productCode != null and productCode != ''">product_code,</if>
+            <if test="productionLine != null and productionLine != ''">production_line,</if>
+            <if test="locationCode != null and locationCode != ''">location_code,</if>
+            <if test="equipmentNo != null">equipment_no,</if>
+            <if test="paramCode != null and paramCode != ''">param_code,</if>
+            <if test="paramValue != null and paramValue != ''">param_value,</if>
+            <if test="paramUpper != null">param_upper,</if>
+            <if test="paramLower != null">param_lower,</if>
+            <if test="paramStandard != null">param_standard,</if>
+            <if test="collectionTime != null">collection_time,</if>
+            <if test="spareField1 != null">spare_field_1,</if>
+            <if test="spareField2 != null">spare_field_2,</if>
+            <if test="createUser != null">create_user,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateUser != null">update_user,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="state != null">state,</if>
+            <if test="paramName != null">param_name,</if>
+            <if test="unit != null">unit,</if>
+            <if test="type != null">type,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="id != null">#{id},</if>
+            <if test="workOrderNo != null and workOrderNo != ''">#{workOrderNo},</if>
+            <if test="sfcCode != null and sfcCode != ''">#{sfcCode},</if>
+            <if test="productCode != null and productCode != ''">#{productCode},</if>
+            <if test="productionLine != null and productionLine != ''">#{productionLine},</if>
+            <if test="locationCode != null and locationCode != ''">#{locationCode},</if>
+            <if test="equipmentNo != null">#{equipmentNo},</if>
+            <if test="paramCode != null and paramCode != ''">#{paramCode},</if>
+            <if test="paramValue != null and paramValue != ''">#{paramValue},</if>
+            <if test="paramUpper != null">#{paramUpper},</if>
+            <if test="paramLower != null">#{paramLower},</if>
+            <if test="paramStandard != null">#{paramStandard},</if>
+            <if test="collectionTime != null">#{collectionTime},</if>
+            <if test="spareField1 != null">#{spareField1},</if>
+            <if test="spareField2 != null">#{spareField2},</if>
+            <if test="createUser != null">#{createUser},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateUser != null">#{updateUser},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="state != null">#{state},</if>
+            <if test="paramName != null">#{paramName},</if>
+            <if test="unit != null">#{unit},</if>
+            <if test="type != null">#{type},</if>
+         </trim>
+    </insert>
+
+    <update id="updateDaParamCollection" parameterType="DaParamCollection">
+        update da_param_collection
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="workOrderNo != null and workOrderNo != ''">work_order_no = #{workOrderNo},</if>
+            <if test="sfcCode != null and sfcCode != ''">sfc_code = #{sfcCode},</if>
+            <if test="productCode != null and productCode != ''">product_code = #{productCode},</if>
+            <if test="productionLine != null and productionLine != ''">production_line = #{productionLine},</if>
+            <if test="locationCode != null and locationCode != ''">location_code = #{locationCode},</if>
+            <if test="equipmentNo != null">equipment_no = #{equipmentNo},</if>
+            <if test="paramCode != null and paramCode != ''">param_code = #{paramCode},</if>
+            <if test="paramValue != null and paramValue != ''">param_value = #{paramValue},</if>
+            <if test="paramUpper != null">param_upper = #{paramUpper},</if>
+            <if test="paramLower != null">param_lower = #{paramLower},</if>
+            <if test="paramStandard != null">param_standard = #{paramStandard},</if>
+            <if test="collectionTime != null">collection_time = #{collectionTime},</if>
+            <if test="spareField1 != null">spare_field_1 = #{spareField1},</if>
+            <if test="spareField2 != null">spare_field_2 = #{spareField2},</if>
+            <if test="createUser != null">create_user = #{createUser},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateUser != null">update_user = #{updateUser},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="state != null">state = #{state},</if>
+            <if test="paramName != null">param_name = #{paramName},</if>
+            <if test="unit != null">unit = #{unit},</if>
+            <if test="type != null">type = #{type},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteDaParamCollectionById" parameterType="Long">
+        delete from da_param_collection where id = #{id}
+    </delete>
+
+    <delete id="deleteDaParamCollectionByIds" parameterType="String">
+        delete from da_param_collection where id in 
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>
\ No newline at end of file
diff --git a/jcdm-main/src/main/resources/mapper/da/passingStationCollection/DaPassingStationCollectionMapper.xml b/jcdm-main/src/main/resources/mapper/da/passingStationCollection/DaPassingStationCollectionMapper.xml
new file mode 100644
index 0000000..3eca8e2
--- /dev/null
+++ b/jcdm-main/src/main/resources/mapper/da/passingStationCollection/DaPassingStationCollectionMapper.xml
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.main.da.passingStationCollection.mapper.DaPassingStationCollectionMapper">
+    
+    <resultMap type="DaPassingStationCollection" id="DaPassingStationCollectionResult">
+        <result property="id"    column="id"    />
+        <result property="workOrderNo"    column="work_order_no"    />
+        <result property="sfcCode"    column="sfc_code"    />
+        <result property="productCode"    column="product_code"    />
+        <result property="productionLine"    column="production_line"    />
+        <result property="locationCode"    column="location_code"    />
+        <result property="equipmentNo"    column="equipment_no"    />
+        <result property="inboundTime"    column="inbound_time"    />
+        <result property="outboundTime"    column="outbound_time"    />
+        <result property="inRsSign"    column="in_rs_sign"    />
+        <result property="inMsgSign"    column="in_msg_sign"    />
+        <result property="outRsSign"    column="out_rs_sign"    />
+        <result property="outMsgSign"    column="out_msg_sign"    />
+        <result property="collectionTime"    column="collection_time"    />
+        <result property="spareField1"    column="spare_field_1"    />
+        <result property="spareField2"    column="spare_field_2"    />
+        <result property="createUser"    column="create_user"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateUser"    column="update_user"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="beatTime"    column="beat_time"    />
+    </resultMap>
+
+    <sql id="selectDaPassingStationCollectionVo">
+        select id, work_order_no, sfc_code, product_code, production_line, location_code, equipment_no, inbound_time, outbound_time, in_rs_sign, in_msg_sign, out_rs_sign, out_msg_sign, collection_time, spare_field_1, spare_field_2, create_user, create_time, update_user, update_time, beat_time from da_passing_station_collection
+    </sql>
+
+    <select id="selectDaPassingStationCollectionList" parameterType="DaPassingStationCollection" resultMap="DaPassingStationCollectionResult">
+        <include refid="selectDaPassingStationCollectionVo"/>
+        <where>  
+            <if test="workOrderNo != null  and workOrderNo != ''"> and work_order_no = #{workOrderNo}</if>
+            <if test="sfcCode != null  and sfcCode != ''"> and sfc_code = #{sfcCode}</if>
+            <if test="productCode != null  and productCode != ''"> and product_code = #{productCode}</if>
+            <if test="productionLine != null  and productionLine != ''"> and production_line = #{productionLine}</if>
+            <if test="locationCode != null  and locationCode != ''"> and location_code = #{locationCode}</if>
+            <if test="equipmentNo != null  and equipmentNo != ''"> and equipment_no = #{equipmentNo}</if>
+            <if test="inboundTime != null "> and inbound_time = #{inboundTime}</if>
+            <if test="outboundTime != null "> and outbound_time = #{outboundTime}</if>
+            <if test="outRsSign != null "> and out_rs_sign = #{outRsSign}</if>
+            <if test="outRsSign != null "> and out_rs_sign = #{outRsSign}</if>
+
+        </where>
+    </select>
+    
+    <select id="selectDaPassingStationCollectionById" parameterType="Long" resultMap="DaPassingStationCollectionResult">
+        <include refid="selectDaPassingStationCollectionVo"/>
+        where id = #{id}
+    </select>
+        
+    <insert id="insertDaPassingStationCollection" parameterType="DaPassingStationCollection">
+        insert into da_passing_station_collection
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="id != null">id,</if>
+            <if test="workOrderNo != null">work_order_no,</if>
+            <if test="sfcCode != null">sfc_code,</if>
+            <if test="productCode != null">product_code,</if>
+            <if test="productionLine != null">production_line,</if>
+            <if test="locationCode != null">location_code,</if>
+            <if test="equipmentNo != null">equipment_no,</if>
+            <if test="inboundTime != null">inbound_time,</if>
+            <if test="outboundTime != null">outbound_time,</if>
+            <if test="inRsSign != null">in_rs_sign,</if>
+            <if test="inMsgSign != null">in_msg_sign,</if>
+            <if test="outRsSign != null">out_rs_sign,</if>
+            <if test="outMsgSign != null">out_msg_sign,</if>
+            <if test="collectionTime != null">collection_time,</if>
+            <if test="spareField1 != null">spare_field_1,</if>
+            <if test="spareField2 != null">spare_field_2,</if>
+            <if test="createUser != null">create_user,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateUser != null">update_user,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="beatTime != null">beat_time,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="id != null">#{id},</if>
+            <if test="workOrderNo != null">#{workOrderNo},</if>
+            <if test="sfcCode != null">#{sfcCode},</if>
+            <if test="productCode != null">#{productCode},</if>
+            <if test="productionLine != null">#{productionLine},</if>
+            <if test="locationCode != null">#{locationCode},</if>
+            <if test="equipmentNo != null">#{equipmentNo},</if>
+            <if test="inboundTime != null">#{inboundTime},</if>
+            <if test="outboundTime != null">#{outboundTime},</if>
+            <if test="inRsSign != null">#{inRsSign},</if>
+            <if test="inMsgSign != null">#{inMsgSign},</if>
+            <if test="outRsSign != null">#{outRsSign},</if>
+            <if test="outMsgSign != null">#{outMsgSign},</if>
+            <if test="collectionTime != null">#{collectionTime},</if>
+            <if test="spareField1 != null">#{spareField1},</if>
+            <if test="spareField2 != null">#{spareField2},</if>
+            <if test="createUser != null">#{createUser},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateUser != null">#{updateUser},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="beatTime != null">#{beatTime},</if>
+         </trim>
+    </insert>
+
+    <update id="updateDaPassingStationCollection" parameterType="DaPassingStationCollection">
+        update da_passing_station_collection
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="workOrderNo != null">work_order_no = #{workOrderNo},</if>
+            <if test="sfcCode != null">sfc_code = #{sfcCode},</if>
+            <if test="productCode != null">product_code = #{productCode},</if>
+            <if test="productionLine != null">production_line = #{productionLine},</if>
+            <if test="locationCode != null">location_code = #{locationCode},</if>
+            <if test="equipmentNo != null">equipment_no = #{equipmentNo},</if>
+            <if test="inboundTime != null">inbound_time = #{inboundTime},</if>
+            <if test="outboundTime != null">outbound_time = #{outboundTime},</if>
+            <if test="inRsSign != null">in_rs_sign = #{inRsSign},</if>
+            <if test="inMsgSign != null">in_msg_sign = #{inMsgSign},</if>
+            <if test="outRsSign != null">out_rs_sign = #{outRsSign},</if>
+            <if test="outMsgSign != null">out_msg_sign = #{outMsgSign},</if>
+            <if test="collectionTime != null">collection_time = #{collectionTime},</if>
+            <if test="spareField1 != null">spare_field_1 = #{spareField1},</if>
+            <if test="spareField2 != null">spare_field_2 = #{spareField2},</if>
+            <if test="createUser != null">create_user = #{createUser},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateUser != null">update_user = #{updateUser},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="beatTime != null">beat_time = #{beatTime},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteDaPassingStationCollectionById" parameterType="Long">
+        delete from da_passing_station_collection where id = #{id}
+    </delete>
+
+    <delete id="deleteDaPassingStationCollectionByIds" parameterType="String">
+        delete from da_passing_station_collection where id in 
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>
\ No newline at end of file
diff --git a/jcdm-main/src/main/resources/mapper/em/equipmentAlarm/EmEquipmentAlarmMapper.xml b/jcdm-main/src/main/resources/mapper/em/equipmentAlarm/EmEquipmentAlarmMapper.xml
new file mode 100644
index 0000000..edec65a
--- /dev/null
+++ b/jcdm-main/src/main/resources/mapper/em/equipmentAlarm/EmEquipmentAlarmMapper.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.main.em.equipmentAlarm.mapper.EmEquipmentAlarmMapper">
+
+    <resultMap type="EmEquipmentAlarm" id="EmEquipmentAlarmResult">
+        <result property="id"    column="id"    />
+        <result property="equipmentCode"    column="equipment_code"    />
+        <result property="equipmentName"    column="equipment_name"    />
+        <result property="equipmentType"    column="equipment_type"    />
+        <result property="workshopCode"    column="workshop_code"    />
+        <result property="lineCode"    column="line_code"    />
+        <result property="processesCode"    column="processes_code"    />
+        <result property="errorNo"    column="error_no"    />
+        <result property="errorDesc"    column="error_desc"    />
+        <result property="alarmTime"    column="alarm_time"    />
+        <result property="whetherRecovery"    column="whether_recovery"    />
+        <result property="recoveryTime"    column="recovery_time"    />
+        <result property="spareField1"    column="spare_field_1"    />
+        <result property="spareField2"    column="spare_field_2"    />
+        <result property="spareField3"    column="spare_field_3"    />
+        <result property="spareField4"    column="spare_field_4"    />
+        <result property="remarks"    column="remarks"    />
+    </resultMap>
+
+    <sql id="selectEmEquipmentAlarmVo">
+        select id, equipment_code, equipment_name, equipment_type, workshop_code, line_code, processes_code, error_no, error_desc, alarm_time, whether_recovery, recovery_time, spare_field_1, spare_field_2, spare_field_3, spare_field_4, remarks from em_equipment_alarm
+    </sql>
+
+    <select id="selectEmEquipmentAlarmList" parameterType="EmEquipmentAlarm" resultMap="EmEquipmentAlarmResult">
+        <include refid="selectEmEquipmentAlarmVo"/>
+        <where>  
+            <if test="equipmentCode != null  and equipmentCode != ''"> and equipment_code like concat('%', #{equipmentCode}, '%')</if>
+            <if test="equipmentName != null  and equipmentName != ''"> and equipment_name like concat('%', #{equipmentName}, '%')</if>
+            <if test="equipmentType != null  and equipmentType != ''"> and equipment_type = #{equipmentType}</if>
+            <if test="errorNo != null  and errorNo != ''"> and error_no = #{errorNo}</if>
+        </where>
+    </select>
+    
+    <select id="selectEmEquipmentAlarmById" parameterType="Long" resultMap="EmEquipmentAlarmResult">
+        <include refid="selectEmEquipmentAlarmVo"/>
+        where id = #{id}
+    </select>
+        
+    <insert id="insertEmEquipmentAlarm" parameterType="EmEquipmentAlarm">
+        insert into em_equipment_alarm
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="id != null">id,</if>
+            <if test="equipmentCode != null and equipmentCode != ''">equipment_code,</if>
+            <if test="equipmentName != null and equipmentName != ''">equipment_name,</if>
+            <if test="equipmentType != null and equipmentType != ''">equipment_type,</if>
+            <if test="workshopCode != null">workshop_code,</if>
+            <if test="lineCode != null">line_code,</if>
+            <if test="processesCode != null and processesCode != ''">processes_code,</if>
+            <if test="errorNo != null and errorNo != ''">error_no,</if>
+            <if test="errorDesc != null">error_desc,</if>
+            <if test="alarmTime != null">alarm_time,</if>
+            <if test="whetherRecovery != null">whether_recovery,</if>
+            <if test="recoveryTime != null">recovery_time,</if>
+            <if test="spareField1 != null">spare_field_1,</if>
+            <if test="spareField2 != null">spare_field_2,</if>
+            <if test="spareField3 != null">spare_field_3,</if>
+            <if test="spareField4 != null">spare_field_4,</if>
+            <if test="remarks != null">remarks,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="id != null">#{id},</if>
+            <if test="equipmentCode != null and equipmentCode != ''">#{equipmentCode},</if>
+            <if test="equipmentName != null and equipmentName != ''">#{equipmentName},</if>
+            <if test="equipmentType != null and equipmentType != ''">#{equipmentType},</if>
+            <if test="workshopCode != null">#{workshopCode},</if>
+            <if test="lineCode != null">#{lineCode},</if>
+            <if test="processesCode != null and processesCode != ''">#{processesCode},</if>
+            <if test="errorNo != null and errorNo != ''">#{errorNo},</if>
+            <if test="errorDesc != null">#{errorDesc},</if>
+            <if test="alarmTime != null">#{alarmTime},</if>
+            <if test="whetherRecovery != null">#{whetherRecovery},</if>
+            <if test="recoveryTime != null">#{recoveryTime},</if>
+            <if test="spareField1 != null">#{spareField1},</if>
+            <if test="spareField2 != null">#{spareField2},</if>
+            <if test="spareField3 != null">#{spareField3},</if>
+            <if test="spareField4 != null">#{spareField4},</if>
+            <if test="remarks != null">#{remarks},</if>
+         </trim>
+    </insert>
+
+    <update id="updateEmEquipmentAlarm" parameterType="EmEquipmentAlarm">
+        update em_equipment_alarm
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="equipmentCode != null and equipmentCode != ''">equipment_code = #{equipmentCode},</if>
+            <if test="equipmentName != null and equipmentName != ''">equipment_name = #{equipmentName},</if>
+            <if test="equipmentType != null and equipmentType != ''">equipment_type = #{equipmentType},</if>
+            <if test="workshopCode != null">workshop_code = #{workshopCode},</if>
+            <if test="lineCode != null">line_code = #{lineCode},</if>
+            <if test="processesCode != null and processesCode != ''">processes_code = #{processesCode},</if>
+            <if test="errorNo != null and errorNo != ''">error_no = #{errorNo},</if>
+            <if test="errorDesc != null">error_desc = #{errorDesc},</if>
+            <if test="alarmTime != null">alarm_time = #{alarmTime},</if>
+            <if test="whetherRecovery != null">whether_recovery = #{whetherRecovery},</if>
+            <if test="recoveryTime != null">recovery_time = #{recoveryTime},</if>
+            <if test="spareField1 != null">spare_field_1 = #{spareField1},</if>
+            <if test="spareField2 != null">spare_field_2 = #{spareField2},</if>
+            <if test="spareField3 != null">spare_field_3 = #{spareField3},</if>
+            <if test="spareField4 != null">spare_field_4 = #{spareField4},</if>
+            <if test="remarks != null">remarks = #{remarks},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteEmEquipmentAlarmById" parameterType="Long">
+        delete from em_equipment_alarm where id = #{id}
+    </delete>
+
+    <delete id="deleteEmEquipmentAlarmByIds" parameterType="String">
+        delete from em_equipment_alarm where id in 
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>
\ No newline at end of file
diff --git a/jcdm-main/src/main/resources/mapper/em/equipmentArchives/EmEquipmentArchivesMapper.xml b/jcdm-main/src/main/resources/mapper/em/equipmentArchives/EmEquipmentArchivesMapper.xml
new file mode 100644
index 0000000..a225b25
--- /dev/null
+++ b/jcdm-main/src/main/resources/mapper/em/equipmentArchives/EmEquipmentArchivesMapper.xml
@@ -0,0 +1,155 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.main.em.equipmentArchives.mapper.EmEquipmentArchivesMapper">
+    
+    <resultMap type="EmEquipmentArchives" id="EmEquipmentArchivesResult">
+        <result property="id"    column="id"    />
+        <result property="equipmentCode"    column="equipment_code"    />
+        <result property="equipmentName"    column="equipment_name"    />
+        <result property="equipmentBrand"    column="equipment_brand"    />
+        <result property="equipmentSpec"    column="equipment_spec"    />
+        <result property="equipmentTypeId"    column="equipment_type_id"    />
+        <result property="equipmentTypeCode"    column="equipment_type_code"    />
+        <result property="equipmentTypeName"    column="equipment_type_name"    />
+        <result property="workshopCode"    column="workshop_code"    />
+        <result property="lineCode"    column="line_code"    />
+        <result property="processesCode"    column="processes_code"    />
+        <result property="processesName"    column="processes_name"    />
+        <result property="status"    column="status"    />
+        <result property="remark"    column="remark"    />
+        <result property="createUser"    column="create_user"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateUser"    column="update_user"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="spareField1"    column="spare_field_1"    />
+        <result property="spareField2"    column="spare_field_2"    />
+        <result property="spareField3"    column="spare_field_3"    />
+        <result property="spareField4"    column="spare_field_4"    />
+    </resultMap>
+
+    <sql id="selectEmEquipmentArchivesVo">
+        select id, equipment_code, equipment_name, equipment_brand, equipment_spec, equipment_type_id, equipment_type_code, equipment_type_name, workshop_code, line_code, processes_code, processes_name , status, remark, create_user, create_time, update_user, update_time, spare_field_1, spare_field_2, spare_field_3, spare_field_4 from em_equipment_archives
+    </sql>
+
+    <select id="selectEmEquipmentArchivesList" parameterType="EmEquipmentArchives" resultMap="EmEquipmentArchivesResult">
+        <include refid="selectEmEquipmentArchivesVo"/>
+        <where>  
+            <if test="equipmentCode != null  and equipmentCode != ''"> and equipment_code = #{equipmentCode}</if>
+            <if test="equipmentName != null  and equipmentName != ''"> and equipment_name like concat('%', #{equipmentName}, '%')</if>
+            <if test="equipmentBrand != null  and equipmentBrand != ''"> and equipment_brand = #{equipmentBrand}</if>
+            <if test="equipmentSpec != null  and equipmentSpec != ''"> and equipment_spec = #{equipmentSpec}</if>
+            <if test="equipmentTypeId != null "> and equipment_type_id = #{equipmentTypeId}</if>
+            <if test="equipmentTypeCode != null  and equipmentTypeCode != ''"> and equipment_type_code = #{equipmentTypeCode}</if>
+            <if test="equipmentTypeName != null  and equipmentTypeName != ''"> and equipment_type_name like concat('%', #{equipmentTypeName}, '%')</if>
+            <if test="workshopCode != null  and workshopCode != ''"> and workshop_code = #{workshopCode}</if>
+            <if test="lineCode != null  and lineCode != ''"> and line_code = #{lineCode}</if>
+            <if test="processesName != null  and processesName != ''"> and processes_name like concat('%', #{processesName}, '%')</if>
+            <if test="processesCode != null  and processesCode != ''"> and processes_code = #{processesCode}</if>
+            <if test="status != null  and status != ''"> and status = #{status}</if>
+            <if test="createUser != null  and createUser != ''"> and create_user = #{createUser}</if>
+            <if test="updateUser != null  and updateUser != ''"> and update_user = #{updateUser}</if>
+            <if test="spareField1 != null  and spareField1 != ''"> and spare_field_1 = #{spareField1}</if>
+            <if test="spareField2 != null  and spareField2 != ''"> and spare_field_2 = #{spareField2}</if>
+            <if test="spareField3 != null "> and spare_field_3 = #{spareField3}</if>
+            <if test="spareField4 != null "> and spare_field_4 = #{spareField4}</if>
+        </where>
+    </select>
+    
+    <select id="selectEmEquipmentArchivesById" parameterType="Long" resultMap="EmEquipmentArchivesResult">
+        <include refid="selectEmEquipmentArchivesVo"/>
+        where id = #{id}
+    </select>
+        
+    <insert id="insertEmEquipmentArchives" parameterType="EmEquipmentArchives">
+        insert into em_equipment_archives
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="id != null">id,</if>
+            <if test="equipmentCode != null and equipmentCode != ''">equipment_code,</if>
+            <if test="equipmentName != null and equipmentName != ''">equipment_name,</if>
+            <if test="equipmentBrand != null">equipment_brand,</if>
+            <if test="equipmentSpec != null">equipment_spec,</if>
+            <if test="equipmentTypeId != null">equipment_type_id,</if>
+            <if test="equipmentTypeCode != null">equipment_type_code,</if>
+            <if test="equipmentTypeName != null">equipment_type_name,</if>
+            <if test="workshopCode != null">workshop_code,</if>
+            <if test="lineCode != null">line_code,</if>
+            <if test="processesName != null and processesName != ''">processes_name,</if>
+            <if test="processesCode != null">processes_code,</if>
+            <if test="status != null">status,</if>
+            <if test="remark != null">remark,</if>
+            <if test="createUser != null">create_user,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateUser != null">update_user,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="spareField1 != null">spare_field_1,</if>
+            <if test="spareField2 != null">spare_field_2,</if>
+            <if test="spareField3 != null">spare_field_3,</if>
+            <if test="spareField4 != null">spare_field_4,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="id != null">#{id},</if>
+            <if test="equipmentCode != null and equipmentCode != ''">#{equipmentCode},</if>
+            <if test="equipmentName != null and equipmentName != ''">#{equipmentName},</if>
+            <if test="equipmentBrand != null">#{equipmentBrand},</if>
+            <if test="equipmentSpec != null">#{equipmentSpec},</if>
+            <if test="equipmentTypeId != null">#{equipmentTypeId},</if>
+            <if test="equipmentTypeCode != null">#{equipmentTypeCode},</if>
+            <if test="equipmentTypeName != null">#{equipmentTypeName},</if>
+            <if test="workshopCode != null">#{workshopCode},</if>
+            <if test="lineCode != null">#{lineCode},</if>
+            <if test="processesCode != null">#{processesCode},</if>
+            <if test="processesName != null and processesName != ''">#{processesName},</if>
+            <if test="status != null">#{status},</if>
+            <if test="remark != null">#{remark},</if>
+            <if test="createUser != null">#{createUser},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateUser != null">#{updateUser},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="spareField1 != null">#{spareField1},</if>
+            <if test="spareField2 != null">#{spareField2},</if>
+            <if test="spareField3 != null">#{spareField3},</if>
+            <if test="spareField4 != null">#{spareField4},</if>
+         </trim>
+    </insert>
+
+    <update id="updateEmEquipmentArchives" parameterType="EmEquipmentArchives">
+        update em_equipment_archives
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="equipmentCode != null and equipmentCode != ''">equipment_code = #{equipmentCode},</if>
+            <if test="equipmentName != null and equipmentName != ''">equipment_name = #{equipmentName},</if>
+            <if test="equipmentBrand != null">equipment_brand = #{equipmentBrand},</if>
+            <if test="equipmentSpec != null">equipment_spec = #{equipmentSpec},</if>
+            <if test="equipmentTypeId != null">equipment_type_id = #{equipmentTypeId},</if>
+            <if test="equipmentTypeCode != null">equipment_type_code = #{equipmentTypeCode},</if>
+            <if test="equipmentTypeName != null">equipment_type_name = #{equipmentTypeName},</if>
+            <if test="workshopCode != null">workshop_code = #{workshopCode},</if>
+            <if test="lineCode != null">line_code = #{lineCode},</if>
+            <if test="processesCode != null">processes_code = #{processesCode},</if>
+            <if test="processesName != null and processesName != ''">processes_name = #{processesName},</if>
+            <if test="status != null">status = #{status},</if>
+            <if test="remark != null">remark = #{remark},</if>
+            <if test="createUser != null">create_user = #{createUser},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateUser != null">update_user = #{updateUser},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="spareField1 != null">spare_field_1 = #{spareField1},</if>
+            <if test="spareField2 != null">spare_field_2 = #{spareField2},</if>
+            <if test="spareField3 != null">spare_field_3 = #{spareField3},</if>
+            <if test="spareField4 != null">spare_field_4 = #{spareField4},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteEmEquipmentArchivesById" parameterType="Long">
+        delete from em_equipment_archives where id = #{id}
+    </delete>
+
+    <delete id="deleteEmEquipmentArchivesByIds" parameterType="String">
+        delete from em_equipment_archives where id in 
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>
\ No newline at end of file
diff --git a/jcdm-main/src/main/resources/mapper/em/equipmentStatus/EmEquipmentStatusMapper.xml b/jcdm-main/src/main/resources/mapper/em/equipmentStatus/EmEquipmentStatusMapper.xml
new file mode 100644
index 0000000..91c9cda
--- /dev/null
+++ b/jcdm-main/src/main/resources/mapper/em/equipmentStatus/EmEquipmentStatusMapper.xml
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.main.em.equipmentStatus.mapper.EmEquipmentStatusMapper">
+    
+    <resultMap type="EmEquipmentStatus" id="EmEquipmentStatusResult">
+        <result property="id"    column="id"    />
+        <result property="equipmentNo"    column="equipment_no"    />
+        <result property="equipmentName"    column="equipment_name"    />
+        <result property="workshopCode"    column="workshop_code"    />
+        <result property="productionLineCode"    column="production_line_code"    />
+        <result property="processesCode"    column="processes_code"    />
+        <result property="eqStatus"    column="eq_status"    />
+        <result property="spareField1"    column="spare_field_1"    />
+        <result property="spareField2"    column="spare_field_2"    />
+        <result property="remarks"    column="remarks"    />
+        <result property="updateTime"    column="update_time"    />
+    </resultMap>
+
+    <sql id="selectEmEquipmentStatusVo">
+        select id, equipment_no, equipment_name, workshop_code, production_line_code, processes_code, eq_status, spare_field_1, spare_field_2, remarks, update_time from em_equipment_status
+    </sql>
+
+    <select id="selectEmEquipmentStatusList" parameterType="EmEquipmentStatus" resultMap="EmEquipmentStatusResult">
+        <include refid="selectEmEquipmentStatusVo"/>
+        <where>  
+            <if test="equipmentNo != null  and equipmentNo != ''"> and equipment_no like concat('%', #{equipmentNo}, '%')</if>
+            <if test="equipmentName != null  and equipmentName != ''"> and equipment_name like concat('%', #{equipmentName}, '%')</if>
+            <if test="workshopCode != null  and workshopCode != ''"> and workshop_code like concat('%', #{workshopCode}, '%')</if>
+            <if test="productionLineCode != null  and productionLineCode != ''"> and production_line_code like concat('%', #{productionLineCode}, '%')</if>
+            <if test="processesCode != null  and processesCode != ''"> and processes_code like concat('%', #{processesCode}, '%')</if>
+            <if test="eqStatus != null  and eqStatus != ''"> and eq_status like concat('%', #{eqStatus}, '%')</if>
+        </where>
+    </select>
+    
+    <select id="selectEmEquipmentStatusById" parameterType="Long" resultMap="EmEquipmentStatusResult">
+        <include refid="selectEmEquipmentStatusVo"/>
+        where id = #{id}
+    </select>
+        
+    <insert id="insertEmEquipmentStatus" parameterType="EmEquipmentStatus">
+        insert into em_equipment_status
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="id != null">id,</if>
+            <if test="equipmentNo != null">equipment_no,</if>
+            <if test="equipmentName != null">equipment_name,</if>
+            <if test="workshopCode != null">workshop_code,</if>
+            <if test="productionLineCode != null">production_line_code,</if>
+            <if test="processesCode != null">processes_code,</if>
+            <if test="eqStatus != null">eq_status,</if>
+            <if test="spareField1 != null">spare_field_1,</if>
+            <if test="spareField2 != null">spare_field_2,</if>
+            <if test="remarks != null">remarks,</if>
+            <if test="updateTime != null">update_time,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="id != null">#{id},</if>
+            <if test="equipmentNo != null">#{equipmentNo},</if>
+            <if test="equipmentName != null">#{equipmentName},</if>
+            <if test="workshopCode != null">#{workshopCode},</if>
+            <if test="productionLineCode != null">#{productionLineCode},</if>
+            <if test="processesCode != null">#{processesCode},</if>
+            <if test="eqStatus != null">#{eqStatus},</if>
+            <if test="spareField1 != null">#{spareField1},</if>
+            <if test="spareField2 != null">#{spareField2},</if>
+            <if test="remarks != null">#{remarks},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+         </trim>
+    </insert>
+
+    <update id="updateEmEquipmentStatus" parameterType="EmEquipmentStatus">
+        update em_equipment_status
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="equipmentNo != null">equipment_no = #{equipmentNo},</if>
+            <if test="equipmentName != null">equipment_name = #{equipmentName},</if>
+            <if test="workshopCode != null">workshop_code = #{workshopCode},</if>
+            <if test="productionLineCode != null">production_line_code = #{productionLineCode},</if>
+            <if test="processesCode != null">processes_code = #{processesCode},</if>
+            <if test="eqStatus != null">eq_status = #{eqStatus},</if>
+            <if test="spareField1 != null">spare_field_1 = #{spareField1},</if>
+            <if test="spareField2 != null">spare_field_2 = #{spareField2},</if>
+            <if test="remarks != null">remarks = #{remarks},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteEmEquipmentStatusById" parameterType="Long">
+        delete from em_equipment_status where id = #{id}
+    </delete>
+
+    <delete id="deleteEmEquipmentStatusByIds" parameterType="String">
+        delete from em_equipment_status where id in 
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>
\ No newline at end of file
diff --git a/jcdm-main/src/main/resources/mapper/om/productionOrde/OmProductionOrdeInfoMapper.xml b/jcdm-main/src/main/resources/mapper/om/productionOrde/OmProductionOrdeInfoMapper.xml
new file mode 100644
index 0000000..5aee192
--- /dev/null
+++ b/jcdm-main/src/main/resources/mapper/om/productionOrde/OmProductionOrdeInfoMapper.xml
@@ -0,0 +1,221 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.main.om.productionOrde.mapper.OmProductionOrdeInfoMapper">
+    
+    <resultMap type="OmProductionOrdeInfo" id="OmProductionOrdeInfoResult">
+        <result property="id"    column="id"    />
+        <result property="workOrderNo"    column="work_order_no"    />
+        <result property="salesOrderCode"    column="sales_order_code"    />
+        <result property="productCode"    column="product_code"    />
+        <result property="productName"    column="product_name"    />
+        <result property="workshopCode"    column="workshop_code"    />
+        <result property="lineCode"    column="line_code"    />
+        <result property="routeCode"    column="route_code"    />
+        <result property="bomCode"    column="bom_code"    />
+        <result property="recipeCode"    column="recipe_code"    />
+        <result property="planQty"    column="plan_qty"    />
+        <result property="actualQty"    column="actual_qty"    />
+        <result property="badQty"    column="bad_qty"    />
+        <result property="scrapQty"    column="scrap_qty"    />
+        <result property="repairQty"    column="repair_qty"    />
+        <result property="actualOnlineQty"    column="actual_online_qty"    />
+        <result property="onlineCompletionMark"    column="online_completion_mark"    />
+        <result property="demandDate"    column="demand_date"    />
+        <result property="planStartTime"    column="plan_start_time"    />
+        <result property="planEndTime"    column="plan_end_time"    />
+        <result property="actualStartTime"    column="actual_start_time"    />
+        <result property="actualEndTime"    column="actual_end_time"    />
+        <result property="serialNumber"    column="serial_number"    />
+        <result property="orderStatus"    column="order_status"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="createUser"    column="create_user"    />
+        <result property="updateUser"    column="update_user"    />
+        <result property="remarks"    column="remarks"    />
+        <result property="streamNumber"    column="stream_number"    />
+        <result property="custom"    column="custom"    />
+        <result property="marketAreaCode"    column="market_area_code"    />
+        <result property="softwareVersionCode"    column="software_version_code"    />
+        <result property="productCompanyCode"    column="product_company_code"    />
+        <result property="spareField1"    column="spare_field_1"    />
+        <result property="spareField2"    column="spare_field_2"    />
+        <result property="spareField3"    column="spare_field_3"    />
+        <result property="spareField4"    column="spare_field_4"    />
+    </resultMap>
+
+    <sql id="selectOmProductionOrdeInfoVo">
+        select id, work_order_no, sales_order_code, product_code, product_name, workshop_code, line_code, route_code, bom_code, recipe_code, plan_qty, actual_qty, bad_qty, scrap_qty, repair_qty, actual_online_qty, online_completion_mark, demand_date, plan_start_time, plan_end_time, actual_start_time, actual_end_time, serial_number, order_status, create_time, update_time, create_user, update_user, remarks, stream_number, custom, market_area_code, software_version_code, product_company_code, spare_field_1, spare_field_2, spare_field_3, spare_field_4 from om_production_orde_info
+    </sql>
+
+    <select id="selectOmProductionOrdeInfoList" parameterType="OmProductionOrdeInfo" resultMap="OmProductionOrdeInfoResult">
+        <include refid="selectOmProductionOrdeInfoVo"/>
+        <where>
+            <if test="id != null  and id != ''"> and id like concat('%', #{id}, '%')</if>
+            <if test="workOrderNo != null  and workOrderNo != ''"> and work_order_no like concat('%', #{workOrderNo}, '%')</if>
+            <if test="salesOrderCode != null  and salesOrderCode != ''"> and sales_order_code like concat('%', #{salesOrderCode}, '%')</if>
+            <if test="productCode != null  and productCode != ''"> and product_code like concat('%', #{productCode}, '%')</if>
+            <if test="productName != null  and productName != ''"> and product_name like concat('%', #{productName}, '%')</if>
+            <if test="workshopCode != null  and workshopCode != ''"> and workshop_code like concat('%', #{workshopCode}, '%')</if>
+            <if test="lineCode != null  and lineCode != ''"> and line_code like concat('%', #{lineCode}, '%')</if>
+            <if test="routeCode != null  and routeCode != ''"> and route_code like concat('%', #{routeCode}, '%')</if>
+            <if test="bomCode != null  and bomCode != ''"> and bom_code like concat('%', #{bomCode}, '%')</if>
+            <if test="recipeCode != null  and recipeCode != ''"> and recipe_code like concat('%', #{recipeCode}, '%')</if>
+            <if test="orderStatus != null  and orderStatus != ''"> and order_status = #{orderStatus}</if>
+            <if test="custom != null  and custom != ''"> and custom like concat('%', #{custom}, '%')</if>
+            <if test="marketAreaCode != null  and marketAreaCode != ''"> and market_area_code like concat('%', #{marketAreaCode}, '%')</if>
+            <if test="softwareVersionCode != null  and softwareVersionCode != ''"> and software_version_code like concat('%', #{softwareVersionCode}, '%')</if>
+            <if test="productCompanyCode != null  and productCompanyCode != ''"> and product_company_code like concat('%', #{productCompanyCode}, '%')</if>
+        </where>
+        ORDER BY stream_number DESC
+    </select>
+    
+    <select id="selectOmProductionOrdeInfoById" parameterType="Long" resultMap="OmProductionOrdeInfoResult">
+        <include refid="selectOmProductionOrdeInfoVo"/>
+        where id = #{id}
+    </select>
+        
+    <insert id="insertOmProductionOrdeInfo" parameterType="OmProductionOrdeInfo">
+        insert into om_production_orde_info
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="id != null">id,</if>
+            <if test="workOrderNo != null">work_order_no,</if>
+            <if test="salesOrderCode != null">sales_order_code,</if>
+            <if test="productCode != null">product_code,</if>
+            <if test="productName != null">product_name,</if>
+            <if test="workshopCode != null">workshop_code,</if>
+            <if test="lineCode != null">line_code,</if>
+            <if test="routeCode != null">route_code,</if>
+            <if test="bomCode != null">bom_code,</if>
+            <if test="recipeCode != null">recipe_code,</if>
+            <if test="planQty != null">plan_qty,</if>
+            <if test="actualQty != null">actual_qty,</if>
+            <if test="badQty != null">bad_qty,</if>
+            <if test="scrapQty != null">scrap_qty,</if>
+            <if test="repairQty != null">repair_qty,</if>
+            <if test="actualOnlineQty != null">actual_online_qty,</if>
+            <if test="onlineCompletionMark != null">online_completion_mark,</if>
+            <if test="demandDate != null">demand_date,</if>
+            <if test="planStartTime != null">plan_start_time,</if>
+            <if test="planEndTime != null">plan_end_time,</if>
+            <if test="actualStartTime != null">actual_start_time,</if>
+            <if test="actualEndTime != null">actual_end_time,</if>
+            <if test="serialNumber != null">serial_number,</if>
+            <if test="orderStatus != null">order_status,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="createUser != null">create_user,</if>
+            <if test="updateUser != null">update_user,</if>
+            <if test="remarks != null">remarks,</if>
+            <if test="streamNumber != null">stream_number,</if>
+            <if test="custom != null">custom,</if>
+            <if test="marketAreaCode != null">market_area_code,</if>
+            <if test="softwareVersionCode != null">software_version_code,</if>
+            <if test="productCompanyCode != null">product_company_code,</if>
+            <if test="spareField1 != null">spare_field_1,</if>
+            <if test="spareField2 != null">spare_field_2,</if>
+            <if test="spareField3 != null">spare_field_3,</if>
+            <if test="spareField4 != null">spare_field_4,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="id != null">#{id},</if>
+            <if test="workOrderNo != null">#{workOrderNo},</if>
+            <if test="salesOrderCode != null">#{salesOrderCode},</if>
+            <if test="productCode != null">#{productCode},</if>
+            <if test="productName != null">#{productName},</if>
+            <if test="workshopCode != null">#{workshopCode},</if>
+            <if test="lineCode != null">#{lineCode},</if>
+            <if test="routeCode != null">#{routeCode},</if>
+            <if test="bomCode != null">#{bomCode},</if>
+            <if test="recipeCode != null">#{recipeCode},</if>
+            <if test="planQty != null">#{planQty},</if>
+            <if test="actualQty != null">#{actualQty},</if>
+            <if test="badQty != null">#{badQty},</if>
+            <if test="scrapQty != null">#{scrapQty},</if>
+            <if test="repairQty != null">#{repairQty},</if>
+            <if test="actualOnlineQty != null">#{actualOnlineQty},</if>
+            <if test="onlineCompletionMark != null">#{onlineCompletionMark},</if>
+            <if test="demandDate != null">#{demandDate},</if>
+            <if test="planStartTime != null">#{planStartTime},</if>
+            <if test="planEndTime != null">#{planEndTime},</if>
+            <if test="actualStartTime != null">#{actualStartTime},</if>
+            <if test="actualEndTime != null">#{actualEndTime},</if>
+            <if test="serialNumber != null">#{serialNumber},</if>
+            <if test="orderStatus != null">#{orderStatus},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="createUser != null">#{createUser},</if>
+            <if test="updateUser != null">#{updateUser},</if>
+            <if test="remarks != null">#{remarks},</if>
+            <if test="streamNumber != null">#{streamNumber},</if>
+            <if test="custom != null">#{custom},</if>
+            <if test="marketAreaCode != null">#{marketAreaCode},</if>
+            <if test="softwareVersionCode != null">#{softwareVersionCode},</if>
+            <if test="productCompanyCode != null">#{productCompanyCode},</if>
+            <if test="spareField1 != null">#{spareField1},</if>
+            <if test="spareField2 != null">#{spareField2},</if>
+            <if test="spareField3 != null">#{spareField3},</if>
+            <if test="spareField4 != null">#{spareField4},</if>
+         </trim>
+    </insert>
+
+    <update id="updateOmProductionOrdeInfo" parameterType="OmProductionOrdeInfo">
+        update om_production_orde_info
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="workOrderNo != null">work_order_no = #{workOrderNo},</if>
+            <if test="salesOrderCode != null">sales_order_code = #{salesOrderCode},</if>
+            <if test="productCode != null">product_code = #{productCode},</if>
+            <if test="productName != null">product_name = #{productName},</if>
+            <if test="workshopCode != null">workshop_code = #{workshopCode},</if>
+            <if test="lineCode != null">line_code = #{lineCode},</if>
+            <if test="routeCode != null">route_code = #{routeCode},</if>
+            <if test="bomCode != null">bom_code = #{bomCode},</if>
+            <if test="recipeCode != null">recipe_code = #{recipeCode},</if>
+            <if test="planQty != null">plan_qty = #{planQty},</if>
+            <if test="actualQty != null">actual_qty = #{actualQty},</if>
+            <if test="badQty != null">bad_qty = #{badQty},</if>
+            <if test="scrapQty != null">scrap_qty = #{scrapQty},</if>
+            <if test="repairQty != null">repair_qty = #{repairQty},</if>
+            <if test="actualOnlineQty != null">actual_online_qty = #{actualOnlineQty},</if>
+            <if test="onlineCompletionMark != null">online_completion_mark = #{onlineCompletionMark},</if>
+            <if test="demandDate != null">demand_date = #{demandDate},</if>
+            <if test="planStartTime != null">plan_start_time = #{planStartTime},</if>
+            <if test="planEndTime != null">plan_end_time = #{planEndTime},</if>
+            <if test="actualStartTime != null">actual_start_time = #{actualStartTime},</if>
+            <if test="actualEndTime != null">actual_end_time = #{actualEndTime},</if>
+            <if test="serialNumber != null">serial_number = #{serialNumber},</if>
+            <if test="orderStatus != null">order_status = #{orderStatus},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="createUser != null">create_user = #{createUser},</if>
+            <if test="updateUser != null">update_user = #{updateUser},</if>
+            <if test="remarks != null">remarks = #{remarks},</if>
+            <if test="streamNumber != null">stream_number = #{streamNumber},</if>
+            <if test="custom != null">custom = #{custom},</if>
+            <if test="marketAreaCode != null">market_area_code = #{marketAreaCode},</if>
+            <if test="softwareVersionCode != null">software_version_code = #{softwareVersionCode},</if>
+            <if test="productCompanyCode != null">product_company_code = #{productCompanyCode},</if>
+            <if test="spareField1 != null">spare_field_1 = #{spareField1},</if>
+            <if test="spareField2 != null">spare_field_2 = #{spareField2},</if>
+            <if test="spareField3 != null">spare_field_3 = #{spareField3},</if>
+            <if test="spareField4 != null">spare_field_4 = #{spareField4},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteOmProductionOrdeInfoById" parameterType="Long">
+        delete from om_production_orde_info where id = #{id}
+    </delete>
+
+    <delete id="deleteOmProductionOrdeInfoByIds" parameterType="String">
+        delete from om_production_orde_info where id in 
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+
+    <select id="getMaxStreamNumber" resultType="Integer">
+        SELECT MAX(stream_number) AS streamNumber FROM om_production_orde_info
+    </select>
+</mapper>
\ No newline at end of file
diff --git a/jcdm-main/src/main/resources/mapper/om/workReport/OmWorkReportMapper.xml b/jcdm-main/src/main/resources/mapper/om/workReport/OmWorkReportMapper.xml
new file mode 100644
index 0000000..c50fcd1
--- /dev/null
+++ b/jcdm-main/src/main/resources/mapper/om/workReport/OmWorkReportMapper.xml
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.main.om.workReport.mapper.OmWorkReportMapper">
+    
+    <resultMap type="OmWorkReport" id="OmWorkReportResult">
+        <result property="id"    column="id"    />
+        <result property="workOrderCode"    column="work_order_code"    />
+        <result property="sfcCode"    column="sfc_code"    />
+        <result property="productCode"    column="product_code"    />
+        <result property="productName"    column="product_name"    />
+        <result property="upTime"    column="up_time"    />
+        <result property="offlineTime"    column="offline_time"    />
+        <result property="status"    column="status"    />
+        <result property="createUser"    column="create_user"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateUser"    column="update_user"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="remark"    column="remark"    />
+        <result property="spareField1"    column="spare_field_1"    />
+        <result property="spareField2"    column="spare_field_2"    />
+        <result property="spareField3"    column="spare_field_3"    />
+        <result property="spareField4"    column="spare_field_4"    />
+    </resultMap>
+
+    <sql id="selectOmWorkReportVo">
+        select id, work_order_code, sfc_code, product_code, product_name, up_time, offline_time, status, create_user, create_time, update_user, update_time, remark, spare_field_1, spare_field_2, spare_field_3, spare_field_4 from om_work_report
+    </sql>
+
+    <select id="selectOmWorkReportList" parameterType="OmWorkReport" resultMap="OmWorkReportResult">
+        <include refid="selectOmWorkReportVo"/>
+        <where>  
+            <if test="workOrderCode != null  and workOrderCode != ''"> and work_order_code = #{workOrderCode}</if>
+            <if test="sfcCode != null  and sfcCode != ''"> and sfc_code = #{sfcCode}</if>
+            <if test="productCode != null  and productCode != ''"> and product_code = #{productCode}</if>
+            <if test="productName != null  and productName != ''"> and product_name like concat('%', #{productName}, '%')</if>
+            <if test="upTime != null  and upTime != ''"> and up_time = #{upTime}</if>
+            <if test="offlineTime != null  and offlineTime != ''"> and offline_time = #{offlineTime}</if>
+            <if test="status != null  and status != ''"> and status = #{status}</if>
+            <if test="createUser != null  and createUser != ''"> and create_user = #{createUser}</if>
+            <if test="updateUser != null  and updateUser != ''"> and update_user = #{updateUser}</if>
+            <if test="spareField1 != null  and spareField1 != ''"> and spare_field_1 = #{spareField1}</if>
+            <if test="spareField2 != null  and spareField2 != ''"> and spare_field_2 = #{spareField2}</if>
+            <if test="spareField3 != null  and spareField3 != ''"> and spare_field_3 = #{spareField3}</if>
+            <if test="spareField4 != null  and spareField4 != ''"> and spare_field_4 = #{spareField4}</if>
+        </where>
+    </select>
+    
+    <select id="selectOmWorkReportById" parameterType="Long" resultMap="OmWorkReportResult">
+        <include refid="selectOmWorkReportVo"/>
+        where id = #{id}
+    </select>
+        
+    <insert id="insertOmWorkReport" parameterType="OmWorkReport" useGeneratedKeys="true" keyProperty="id">
+        insert into om_work_report
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="workOrderCode != null">work_order_code,</if>
+            <if test="sfcCode != null">sfc_code,</if>
+            <if test="productCode != null">product_code,</if>
+            <if test="productName != null">product_name,</if>
+            <if test="upTime != null">up_time,</if>
+            <if test="offlineTime != null">offline_time,</if>
+            <if test="status != null">status,</if>
+            <if test="createUser != null">create_user,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateUser != null">update_user,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="remark != null">remark,</if>
+            <if test="spareField1 != null">spare_field_1,</if>
+            <if test="spareField2 != null">spare_field_2,</if>
+            <if test="spareField3 != null">spare_field_3,</if>
+            <if test="spareField4 != null">spare_field_4,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="workOrderCode != null">#{workOrderCode},</if>
+            <if test="sfcCode != null">#{sfcCode},</if>
+            <if test="productCode != null">#{productCode},</if>
+            <if test="productName != null">#{productName},</if>
+            <if test="upTime != null">#{upTime},</if>
+            <if test="offlineTime != null">#{offlineTime},</if>
+            <if test="status != null">#{status},</if>
+            <if test="createUser != null">#{createUser},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateUser != null">#{updateUser},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="remark != null">#{remark},</if>
+            <if test="spareField1 != null">#{spareField1},</if>
+            <if test="spareField2 != null">#{spareField2},</if>
+            <if test="spareField3 != null">#{spareField3},</if>
+            <if test="spareField4 != null">#{spareField4},</if>
+         </trim>
+    </insert>
+
+    <update id="updateOmWorkReport" parameterType="OmWorkReport">
+        update om_work_report
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="workOrderCode != null">work_order_code = #{workOrderCode},</if>
+            <if test="sfcCode != null">sfc_code = #{sfcCode},</if>
+            <if test="productCode != null">product_code = #{productCode},</if>
+            <if test="productName != null">product_name = #{productName},</if>
+            <if test="upTime != null">up_time = #{upTime},</if>
+            <if test="offlineTime != null">offline_time = #{offlineTime},</if>
+            <if test="status != null">status = #{status},</if>
+            <if test="createUser != null">create_user = #{createUser},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateUser != null">update_user = #{updateUser},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="remark != null">remark = #{remark},</if>
+            <if test="spareField1 != null">spare_field_1 = #{spareField1},</if>
+            <if test="spareField2 != null">spare_field_2 = #{spareField2},</if>
+            <if test="spareField3 != null">spare_field_3 = #{spareField3},</if>
+            <if test="spareField4 != null">spare_field_4 = #{spareField4},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteOmWorkReportById" parameterType="Long">
+        delete from om_work_report where id = #{id}
+    </delete>
+
+    <delete id="deleteOmWorkReportByIds" parameterType="String">
+        delete from om_work_report where id in 
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>
\ No newline at end of file
diff --git a/jcdm-main/src/main/resources/mapper/rm/repairData/RmRepairDataMapper.xml b/jcdm-main/src/main/resources/mapper/rm/repairData/RmRepairDataMapper.xml
new file mode 100644
index 0000000..458e616
--- /dev/null
+++ b/jcdm-main/src/main/resources/mapper/rm/repairData/RmRepairDataMapper.xml
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.main.rm.repairData.mapper.RmRepairDataMapper">
+    
+    <resultMap type="RmRepairData" id="RmRepairDataResult">
+        <result property="id"    column="id"    />
+        <result property="snCode"    column="sn_code"    />
+        <result property="boxCode"    column="box_code"    />
+        <result property="processesCode"    column="processes_code"    />
+        <result property="tightenFrequency"    column="tighten_frequency"    />
+        <result property="tightenPiecesNumber"    column="tighten_pieces_number"    />
+        <result property="torqueForce"    column="torque_force"    />
+        <result property="angle"    column="angle"    />
+        <result property="result"    column="result"    />
+        <result property="createUser"    column="create_user"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="updateUser"    column="update_user"    />
+        <result property="remarks"    column="remarks"    />
+        <result property="spareField1"    column="spare_field_1"    />
+        <result property="spareField2"    column="spare_field_2"    />
+        <result property="station"    column="station"    />
+
+    </resultMap>
+
+    <sql id="selectRmRepairDataVo">
+        select id, sn_code, box_code, processes_code, tighten_frequency, tighten_pieces_number, torque_force, angle, result, create_user, create_time, update_time, update_user, remarks, spare_field_1, spare_field_2,station from rm_repair_data
+    </sql>
+
+    <select id="selectRmRepairDataList" parameterType="RmRepairData" resultMap="RmRepairDataResult">
+        <include refid="selectRmRepairDataVo"/>
+        <where>  
+            <if test="snCode != null  and snCode != ''"> and sn_code = #{snCode}</if>
+            <if test="boxCode != null  and boxCode != ''"> and box_code = #{boxCode}</if>
+            <if test="processesCode != null  and processesCode != ''"> and processes_code = #{processesCode}</if>
+            <if test="tightenFrequency != null  and tightenFrequency != ''"> and tighten_frequency = #{tightenFrequency}</if>
+            <if test="tightenPiecesNumber != null  and tightenPiecesNumber != ''"> and tighten_pieces_number = #{tightenPiecesNumber}</if>
+            <if test="torqueForce != null  and torqueForce != ''"> and torque_force = #{torqueForce}</if>
+            <if test="angle != null  and angle != ''"> and angle = #{angle}</if>
+            <if test="result != null  and result != ''"> and result = #{result}</if>
+            <if test="createUser != null  and createUser != ''"> and create_user = #{createUser}</if>
+            <if test="updateUser != null  and updateUser != ''"> and update_user = #{updateUser}</if>
+            <if test="remarks != null  and remarks != ''"> and remarks = #{remarks}</if>
+            <if test="spareField1 != null  and spareField1 != ''"> and spare_field_1 = #{spareField1}</if>
+            <if test="spareField2 != null  and spareField2 != ''"> and spare_field_2 = #{spareField2}</if>
+            <if test="station != null  and station != ''"> and station = #{station}</if>
+
+        </where>
+    </select>
+    
+    <select id="selectRmRepairDataById" parameterType="Long" resultMap="RmRepairDataResult">
+        <include refid="selectRmRepairDataVo"/>
+        where id = #{id}
+    </select>
+        
+    <insert id="insertRmRepairData" parameterType="RmRepairData" useGeneratedKeys="true" keyProperty="id">
+        insert into rm_repair_data
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="snCode != null">sn_code,</if>
+            <if test="boxCode != null">box_code,</if>
+            <if test="processesCode != null">processes_code,</if>
+            <if test="tightenFrequency != null">tighten_frequency,</if>
+            <if test="tightenPiecesNumber != null">tighten_pieces_number,</if>
+            <if test="torqueForce != null">torque_force,</if>
+            <if test="angle != null">angle,</if>
+            <if test="result != null">result,</if>
+            <if test="createUser != null">create_user,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="updateUser != null">update_user,</if>
+            <if test="remarks != null">remarks,</if>
+            <if test="spareField1 != null">spare_field_1,</if>
+            <if test="spareField2 != null">spare_field_2,</if>
+            <if test="station != null">station,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="snCode != null">#{snCode},</if>
+            <if test="boxCode != null">#{boxCode},</if>
+            <if test="processesCode != null">#{processesCode},</if>
+            <if test="tightenFrequency != null">#{tightenFrequency},</if>
+            <if test="tightenPiecesNumber != null">#{tightenPiecesNumber},</if>
+            <if test="torqueForce != null">#{torqueForce},</if>
+            <if test="angle != null">#{angle},</if>
+            <if test="result != null">#{result},</if>
+            <if test="createUser != null">#{createUser},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="updateUser != null">#{updateUser},</if>
+            <if test="remarks != null">#{remarks},</if>
+            <if test="spareField1 != null">#{spareField1},</if>
+            <if test="spareField2 != null">#{spareField2},</if>
+            <if test="station != null">#{station},</if>
+         </trim>
+    </insert>
+
+    <update id="updateRmRepairData" parameterType="RmRepairData">
+        update rm_repair_data
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="snCode != null">sn_code = #{snCode},</if>
+            <if test="boxCode != null">box_code = #{boxCode},</if>
+            <if test="processesCode != null">processes_code = #{processesCode},</if>
+            <if test="tightenFrequency != null">tighten_frequency = #{tightenFrequency},</if>
+            <if test="tightenPiecesNumber != null">tighten_pieces_number = #{tightenPiecesNumber},</if>
+            <if test="torqueForce != null">torque_force = #{torqueForce},</if>
+            <if test="angle != null">angle = #{angle},</if>
+            <if test="result != null">result = #{result},</if>
+            <if test="createUser != null">create_user = #{createUser},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="updateUser != null">update_user = #{updateUser},</if>
+            <if test="remarks != null">remarks = #{remarks},</if>
+            <if test="spareField1 != null">spare_field_1 = #{spareField1},</if>
+            <if test="spareField2 != null">spare_field_2 = #{spareField2},</if>
+            <if test="station != null">station = #{station},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteRmRepairDataById" parameterType="Long">
+        delete from rm_repair_data where id = #{id}
+    </delete>
+
+    <delete id="deleteRmRepairDataByIds" parameterType="String">
+        delete from rm_repair_data where id in 
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>
\ No newline at end of file
diff --git a/jcdm-main/src/main/resources/mapper/rm/repairRecord/RmRepairRecordMapper.xml b/jcdm-main/src/main/resources/mapper/rm/repairRecord/RmRepairRecordMapper.xml
new file mode 100644
index 0000000..ae239d0
--- /dev/null
+++ b/jcdm-main/src/main/resources/mapper/rm/repairRecord/RmRepairRecordMapper.xml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.main.rm.repairRecord.mapper.RmRepairRecordMapper">
+    
+    <resultMap type="RmRepairRecord" id="RmRepairRecordResult">
+        <result property="id"    column="id"    />
+        <result property="snCode"    column="sn_code"    />
+        <result property="repairIdentification"    column="repair_identification"    />
+        <result property="boxCode"    column="box_code"    />
+        <result property="processesCode"    column="processes_code"    />
+        <result property="originalResult"    column="original_result"    />
+        <result property="createUser"    column="create_user"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="updateUser"    column="update_user"    />
+        <result property="repairResults"    column="repair_results"    />
+        <result property="status"    column="status"    />
+        <result property="remarks"    column="remarks"    />
+        <result property="spareField1"    column="spare_field_1"    />
+        <result property="spareField2"    column="spare_field_2"    />
+    </resultMap>
+
+    <sql id="selectRmRepairRecordVo">
+        select id, sn_code, repair_identification, box_code, processes_code, original_result, create_user, create_time, update_time, update_user, repair_results, status, remarks, spare_field_1, spare_field_2,repair_time from rm_repair_record
+    </sql>
+
+    <select id="selectRmRepairRecordList" parameterType="RmRepairRecord" resultMap="RmRepairRecordResult">
+        <include refid="selectRmRepairRecordVo"/>
+        <where>  
+            <if test="snCode != null  and snCode != ''"> and sn_code = #{snCode}</if>
+            <if test="repairIdentification != null  and repairIdentification != ''"> and repair_identification = #{repairIdentification}</if>
+            <if test="boxCode != null  and boxCode != ''"> and box_code = #{boxCode}</if>
+            <if test="processesCode != null  and processesCode != ''"> and processes_code = #{processesCode}</if>
+            <if test="originalResult != null  and originalResult != ''"> and original_result = #{originalResult}</if>
+            <if test="createUser != null  and createUser != ''"> and create_user = #{createUser}</if>
+            <if test="updateUser != null  and updateUser != ''"> and update_user = #{updateUser}</if>
+            <if test="repairResults != null  and repairResults != ''"> and repair_results = #{repairResults}</if>
+            <if test="status != null  and status != ''"> and status = #{status}</if>
+            <if test="remarks != null  and remarks != ''"> and remarks = #{remarks}</if>
+            <if test="spareField1 != null  and spareField1 != ''"> and spare_field_1 = #{spareField1}</if>
+            <if test="spareField2 != null  and spareField2 != ''"> and spare_field_2 = #{spareField2}</if>
+        </where>
+    </select>
+    
+    <select id="selectRmRepairRecordById" parameterType="Long" resultMap="RmRepairRecordResult">
+        <include refid="selectRmRepairRecordVo"/>
+        where id = #{id}
+    </select>
+        
+    <insert id="insertRmRepairRecord" parameterType="RmRepairRecord" useGeneratedKeys="true" keyProperty="id">
+        insert into rm_repair_record
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="snCode != null">sn_code,</if>
+            <if test="repairIdentification != null">repair_identification,</if>
+            <if test="boxCode != null">box_code,</if>
+            <if test="processesCode != null">processes_code,</if>
+            <if test="originalResult != null">original_result,</if>
+            <if test="createUser != null">create_user,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="updateUser != null">update_user,</if>
+            <if test="repairResults != null">repair_results,</if>
+            <if test="status != null">status,</if>
+            <if test="remarks != null">remarks,</if>
+            <if test="spareField1 != null">spare_field_1,</if>
+            <if test="spareField2 != null">spare_field_2,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="snCode != null">#{snCode},</if>
+            <if test="repairIdentification != null">#{repairIdentification},</if>
+            <if test="boxCode != null">#{boxCode},</if>
+            <if test="processesCode != null">#{processesCode},</if>
+            <if test="originalResult != null">#{originalResult},</if>
+            <if test="createUser != null">#{createUser},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="updateUser != null">#{updateUser},</if>
+            <if test="repairResults != null">#{repairResults},</if>
+            <if test="status != null">#{status},</if>
+            <if test="remarks != null">#{remarks},</if>
+            <if test="spareField1 != null">#{spareField1},</if>
+            <if test="spareField2 != null">#{spareField2},</if>
+         </trim>
+    </insert>
+
+    <update id="updateRmRepairRecord" parameterType="RmRepairRecord">
+        update rm_repair_record
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="snCode != null">sn_code = #{snCode},</if>
+            <if test="repairIdentification != null">repair_identification = #{repairIdentification},</if>
+            <if test="boxCode != null">box_code = #{boxCode},</if>
+            <if test="processesCode != null">processes_code = #{processesCode},</if>
+            <if test="originalResult != null">original_result = #{originalResult},</if>
+            <if test="createUser != null">create_user = #{createUser},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="updateUser != null">update_user = #{updateUser},</if>
+            <if test="repairResults != null">repair_results = #{repairResults},</if>
+            <if test="status != null">status = #{status},</if>
+            <if test="remarks != null">remarks = #{remarks},</if>
+            <if test="spareField1 != null">spare_field_1 = #{spareField1},</if>
+            <if test="spareField2 != null">spare_field_2 = #{spareField2},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteRmRepairRecordById" parameterType="Long">
+        delete from rm_repair_record where id = #{id}
+    </delete>
+
+    <delete id="deleteRmRepairRecordByIds" parameterType="String">
+        delete from rm_repair_record where id in 
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>
\ No newline at end of file
diff --git a/jcdm-main/src/main/resources/mapper/sc/stationConf/ScStationConfMapper.xml b/jcdm-main/src/main/resources/mapper/sc/stationConf/ScStationConfMapper.xml
new file mode 100644
index 0000000..887a0bd
--- /dev/null
+++ b/jcdm-main/src/main/resources/mapper/sc/stationConf/ScStationConfMapper.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.main.sc.stationConf.mapper.ScStationConfMapper">
+    
+    <resultMap type="ScStationConf" id="ScStationConfResult">
+        <result property="id"    column="id"    />
+        <result property="processesCode"    column="processes_code"    />
+        <result property="processesName"    column="processes_name"    />
+        <result property="processesType"    column="processes_type"    />
+        <result property="ipAddress"    column="ip_address"    />
+        <result property="spareField1"    column="spare_field_1"    />
+        <result property="spareField2"    column="spare_field_2"    />
+        <result property="spareField3"    column="spare_field_3"    />
+        <result property="spareField4"    column="spare_field_4"    />
+        <result property="createUser"    column="create_user"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateUser"    column="update_user"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="remarks"    column="remarks"    />
+    </resultMap>
+
+    <sql id="selectScStationConfVo">
+        select id, processes_code, processes_name, processes_type, ip_address, spare_field_1, spare_field_2, spare_field_3, spare_field_4, create_user, create_time, update_user, update_time, remarks from sc_station_conf
+    </sql>
+
+    <select id="selectScStationConfList" parameterType="ScStationConf" resultMap="ScStationConfResult">
+        <include refid="selectScStationConfVo"/>
+        <where>  
+            <if test="processesCode != null  and processesCode != ''"> and processes_code = #{processesCode}</if>
+            <if test="processesName != null  and processesName != ''"> and processes_name like concat('%', #{processesName}, '%')</if>
+            <if test="processesType != null  and processesType != ''"> and processes_type = #{processesType}</if>
+            <if test="ipAddress != null  and ipAddress != ''"> and ip_address = #{ipAddress}</if>
+            <if test="spareField1 != null  and spareField1 != ''"> and spare_field_1 = #{spareField1}</if>
+            <if test="spareField2 != null  and spareField2 != ''"> and spare_field_2 = #{spareField2}</if>
+            <if test="spareField3 != null  and spareField3 != ''"> and spare_field_3 = #{spareField3}</if>
+            <if test="spareField4 != null  and spareField4 != ''"> and spare_field_4 = #{spareField4}</if>
+            <if test="createUser != null  and createUser != ''"> and create_user = #{createUser}</if>
+            <if test="updateUser != null  and updateUser != ''"> and update_user = #{updateUser}</if>
+            <if test="remarks != null  and remarks != ''"> and remarks = #{remarks}</if>
+        </where>
+    </select>
+    
+    <select id="selectScStationConfById" parameterType="Long" resultMap="ScStationConfResult">
+        <include refid="selectScStationConfVo"/>
+        where id = #{id}
+    </select>
+        
+    <insert id="insertScStationConf" parameterType="ScStationConf" useGeneratedKeys="true" keyProperty="id">
+        insert into sc_station_conf
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="processesCode != null">processes_code,</if>
+            <if test="processesName != null">processes_name,</if>
+            <if test="processesType != null">processes_type,</if>
+            <if test="ipAddress != null">ip_address,</if>
+            <if test="spareField1 != null">spare_field_1,</if>
+            <if test="spareField2 != null">spare_field_2,</if>
+            <if test="spareField3 != null">spare_field_3,</if>
+            <if test="spareField4 != null">spare_field_4,</if>
+            <if test="createUser != null">create_user,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateUser != null">update_user,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="remarks != null">remarks,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="processesCode != null">#{processesCode},</if>
+            <if test="processesName != null">#{processesName},</if>
+            <if test="processesType != null">#{processesType},</if>
+            <if test="ipAddress != null">#{ipAddress},</if>
+            <if test="spareField1 != null">#{spareField1},</if>
+            <if test="spareField2 != null">#{spareField2},</if>
+            <if test="spareField3 != null">#{spareField3},</if>
+            <if test="spareField4 != null">#{spareField4},</if>
+            <if test="createUser != null">#{createUser},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateUser != null">#{updateUser},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="remarks != null">#{remarks},</if>
+         </trim>
+    </insert>
+
+    <update id="updateScStationConf" parameterType="ScStationConf">
+        update sc_station_conf
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="processesCode != null">processes_code = #{processesCode},</if>
+            <if test="processesName != null">processes_name = #{processesName},</if>
+            <if test="processesType != null">processes_type = #{processesType},</if>
+            <if test="ipAddress != null">ip_address = #{ipAddress},</if>
+            <if test="spareField1 != null">spare_field_1 = #{spareField1},</if>
+            <if test="spareField2 != null">spare_field_2 = #{spareField2},</if>
+            <if test="spareField3 != null">spare_field_3 = #{spareField3},</if>
+            <if test="spareField4 != null">spare_field_4 = #{spareField4},</if>
+            <if test="createUser != null">create_user = #{createUser},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateUser != null">update_user = #{updateUser},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="remarks != null">remarks = #{remarks},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteScStationConfById" parameterType="Long">
+        delete from sc_station_conf where id = #{id}
+    </delete>
+
+    <delete id="deleteScStationConfByIds" parameterType="String">
+        delete from sc_station_conf where id in 
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>
\ No newline at end of file
diff --git a/jcdm-main/src/main/resources/opcua.properties b/jcdm-main/src/main/resources/opcua.properties
new file mode 100644
index 0000000..bc25383
--- /dev/null
+++ b/jcdm-main/src/main/resources/opcua.properties
@@ -0,0 +1,20 @@
+#opcua server
+opcua.server.endpoint.url=opc.tcp://127.0.0.1:49320
+opcua.server.idp.username=
+opcua.server.idp.password=
+
+#opcua client
+opcua.client.app.name=plc
+opcua.client.app.uri=urn:Yyt_PC:UnifiedAutomation:UaExpert
+opcua.client.cert.path=C:/mes/
+opcua.client.cert.file=Yyt_PC-client.pfx
+opcua.client.cert.alias=jlclient-ai
+opcua.client.cert.common.name=UaClient@Jellyleo
+opcua.client.cert.organization=JL
+opcua.client.cert.organization.unit=per
+opcua.client.cert.locality.name=jl
+opcua.client.cert.state.name=JiangSu
+opcua.client.cert.country.code=CN
+opcua.client.cert.dns.name=Jellyleo
+opcua.client.cert.ip.address=administrator
+opcua.client.cert.keystore.password=yyt@8888888888
diff --git a/jcdm-quartz/pom.xml b/jcdm-quartz/pom.xml
new file mode 100644
index 0000000..145876e
--- /dev/null
+++ b/jcdm-quartz/pom.xml
@@ -0,0 +1,40 @@
+<?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">
+    <parent>
+        <artifactId>jcdm</artifactId>
+        <groupId>com.jcdm</groupId>
+        <version>3.8.6</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>jcdm-quartz</artifactId>
+
+    <description>
+        quartz瀹氭椂浠诲姟
+    </description>
+
+    <dependencies>
+
+        <!-- 瀹氭椂浠诲姟 -->
+        <dependency>
+            <groupId>org.quartz-scheduler</groupId>
+            <artifactId>quartz</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.mchange</groupId>
+                    <artifactId>c3p0</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <!-- 閫氱敤宸ュ叿-->
+        <dependency>
+            <groupId>com.jcdm</groupId>
+            <artifactId>jcdm-common</artifactId>
+        </dependency>
+
+    </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/jcdm-quartz/src/main/java/com/jcdm/quartz/config/ScheduleConfig.java b/jcdm-quartz/src/main/java/com/jcdm/quartz/config/ScheduleConfig.java
new file mode 100644
index 0000000..f9f51a2
--- /dev/null
+++ b/jcdm-quartz/src/main/java/com/jcdm/quartz/config/ScheduleConfig.java
@@ -0,0 +1,57 @@
+//package com.jcdm.quartz.config;
+//
+//import org.springframework.context.annotation.Bean;
+//import org.springframework.context.annotation.Configuration;
+//import org.springframework.scheduling.quartz.SchedulerFactoryBean;
+//import javax.sql.DataSource;
+//import java.util.Properties;
+//
+///**
+// * 瀹氭椂浠诲姟閰嶇疆锛堝崟鏈洪儴缃插缓璁垹闄ゆ绫诲拰qrtz鏁版嵁搴撹〃锛岄粯璁よ蛋鍐呭瓨浼氭渶楂樻晥锛�
+// * 
+// * @author jc
+// */
+//@Configuration
+//public class ScheduleConfig
+//{
+//    @Bean
+//    public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource)
+//    {
+//        SchedulerFactoryBean factory = new SchedulerFactoryBean();
+//        factory.setDataSource(dataSource);
+//
+//        // quartz鍙傛暟
+//        Properties prop = new Properties();
+//        prop.put("org.quartz.scheduler.instanceName", "RuoyiScheduler");
+//        prop.put("org.quartz.scheduler.instanceId", "AUTO");
+//        // 绾跨▼姹犻厤缃�
+//        prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
+//        prop.put("org.quartz.threadPool.threadCount", "20");
+//        prop.put("org.quartz.threadPool.threadPriority", "5");
+//        // JobStore閰嶇疆
+//        prop.put("org.quartz.jobStore.class", "org.springframework.scheduling.quartz.LocalDataSourceJobStore");
+//        // 闆嗙兢閰嶇疆
+//        prop.put("org.quartz.jobStore.isClustered", "true");
+//        prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000");
+//        prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "10");
+//        prop.put("org.quartz.jobStore.txIsolationLevelSerializable", "true");
+//
+//        // sqlserver 鍚敤
+//        // prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?");
+//        prop.put("org.quartz.jobStore.misfireThreshold", "12000");
+//        prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");
+//        factory.setQuartzProperties(prop);
+//
+//        factory.setSchedulerName("RuoyiScheduler");
+//        // 寤舵椂鍚姩
+//        factory.setStartupDelay(1);
+//        factory.setApplicationContextSchedulerContextKey("applicationContextKey");
+//        // 鍙�夛紝QuartzScheduler
+//        // 鍚姩鏃舵洿鏂板繁瀛樺湪鐨凧ob锛岃繖鏍峰氨涓嶇敤姣忔淇敼targetObject鍚庡垹闄rtz_job_details琛ㄥ搴旇褰曚簡
+//        factory.setOverwriteExistingJobs(true);
+//        // 璁剧疆鑷姩鍚姩锛岄粯璁や负true
+//        factory.setAutoStartup(true);
+//
+//        return factory;
+//    }
+//}
diff --git a/jcdm-quartz/src/main/java/com/jcdm/quartz/controller/SysJobController.java b/jcdm-quartz/src/main/java/com/jcdm/quartz/controller/SysJobController.java
new file mode 100644
index 0000000..cf770ed
--- /dev/null
+++ b/jcdm-quartz/src/main/java/com/jcdm/quartz/controller/SysJobController.java
@@ -0,0 +1,185 @@
+package com.jcdm.quartz.controller;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.quartz.SchedulerException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.constant.Constants;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.core.page.TableDataInfo;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.common.exception.job.TaskException;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.common.utils.poi.ExcelUtil;
+import com.jcdm.quartz.domain.SysJob;
+import com.jcdm.quartz.service.ISysJobService;
+import com.jcdm.quartz.util.CronUtils;
+import com.jcdm.quartz.util.ScheduleUtils;
+
+/**
+ * 璋冨害浠诲姟淇℃伅鎿嶄綔澶勭悊
+ * 
+ * @author jc
+ */
+@RestController
+@RequestMapping("/monitor/job")
+public class SysJobController extends BaseController
+{
+    @Autowired
+    private ISysJobService jobService;
+
+    /**
+     * 鏌ヨ瀹氭椂浠诲姟鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('monitor:job:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(SysJob sysJob)
+    {
+        startPage();
+        List<SysJob> list = jobService.selectJobList(sysJob);
+        return getDataTable(list);
+    }
+
+    /**
+     * 瀵煎嚭瀹氭椂浠诲姟鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('monitor:job:export')")
+    @Log(title = "瀹氭椂浠诲姟", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, SysJob sysJob)
+    {
+        List<SysJob> list = jobService.selectJobList(sysJob);
+        ExcelUtil<SysJob> util = new ExcelUtil<SysJob>(SysJob.class);
+        util.exportExcel(response, list, "瀹氭椂浠诲姟");
+    }
+
+    /**
+     * 鑾峰彇瀹氭椂浠诲姟璇︾粏淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('monitor:job:query')")
+    @GetMapping(value = "/{jobId}")
+    public AjaxResult getInfo(@PathVariable("jobId") Long jobId)
+    {
+        return success(jobService.selectJobById(jobId));
+    }
+
+    /**
+     * 鏂板瀹氭椂浠诲姟
+     */
+    @PreAuthorize("@ss.hasPermi('monitor:job:add')")
+    @Log(title = "瀹氭椂浠诲姟", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody SysJob job) throws SchedulerException, TaskException
+    {
+        if (!CronUtils.isValid(job.getCronExpression()))
+        {
+            return error("鏂板浠诲姟'" + job.getJobName() + "'澶辫触锛孋ron琛ㄨ揪寮忎笉姝g‘");
+        }
+        else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_RMI))
+        {
+            return error("鏂板浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅厑璁�'rmi'璋冪敤");
+        }
+        else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.LOOKUP_LDAP, Constants.LOOKUP_LDAPS }))
+        {
+            return error("鏂板浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅厑璁�'ldap(s)'璋冪敤");
+        }
+        else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS }))
+        {
+            return error("鏂板浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅厑璁�'http(s)'璋冪敤");
+        }
+        else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), Constants.JOB_ERROR_STR))
+        {
+            return error("鏂板浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆瀛樺湪杩濊");
+        }
+        else if (!ScheduleUtils.whiteList(job.getInvokeTarget()))
+        {
+            return error("鏂板浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅湪鐧藉悕鍗曞唴");
+        }
+        job.setCreateBy(getUsername());
+        return toAjax(jobService.insertJob(job));
+    }
+
+    /**
+     * 淇敼瀹氭椂浠诲姟
+     */
+    @PreAuthorize("@ss.hasPermi('monitor:job:edit')")
+    @Log(title = "瀹氭椂浠诲姟", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody SysJob job) throws SchedulerException, TaskException
+    {
+        if (!CronUtils.isValid(job.getCronExpression()))
+        {
+            return error("淇敼浠诲姟'" + job.getJobName() + "'澶辫触锛孋ron琛ㄨ揪寮忎笉姝g‘");
+        }
+        else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_RMI))
+        {
+            return error("淇敼浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅厑璁�'rmi'璋冪敤");
+        }
+        else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.LOOKUP_LDAP, Constants.LOOKUP_LDAPS }))
+        {
+            return error("淇敼浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅厑璁�'ldap(s)'璋冪敤");
+        }
+        else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS }))
+        {
+            return error("淇敼浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅厑璁�'http(s)'璋冪敤");
+        }
+        else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), Constants.JOB_ERROR_STR))
+        {
+            return error("淇敼浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆瀛樺湪杩濊");
+        }
+        else if (!ScheduleUtils.whiteList(job.getInvokeTarget()))
+        {
+            return error("淇敼浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅湪鐧藉悕鍗曞唴");
+        }
+        job.setUpdateBy(getUsername());
+        return toAjax(jobService.updateJob(job));
+    }
+
+    /**
+     * 瀹氭椂浠诲姟鐘舵�佷慨鏀�
+     */
+    @PreAuthorize("@ss.hasPermi('monitor:job:changeStatus')")
+    @Log(title = "瀹氭椂浠诲姟", businessType = BusinessType.UPDATE)
+    @PutMapping("/changeStatus")
+    public AjaxResult changeStatus(@RequestBody SysJob job) throws SchedulerException
+    {
+        SysJob newJob = jobService.selectJobById(job.getJobId());
+        newJob.setStatus(job.getStatus());
+        return toAjax(jobService.changeStatus(newJob));
+    }
+
+    /**
+     * 瀹氭椂浠诲姟绔嬪嵆鎵ц涓�娆�
+     */
+    @PreAuthorize("@ss.hasPermi('monitor:job:changeStatus')")
+    @Log(title = "瀹氭椂浠诲姟", businessType = BusinessType.UPDATE)
+    @PutMapping("/run")
+    public AjaxResult run(@RequestBody SysJob job) throws SchedulerException
+    {
+        boolean result = jobService.run(job);
+        return result ? success() : error("浠诲姟涓嶅瓨鍦ㄦ垨宸茶繃鏈燂紒");
+    }
+
+    /**
+     * 鍒犻櫎瀹氭椂浠诲姟
+     */
+    @PreAuthorize("@ss.hasPermi('monitor:job:remove')")
+    @Log(title = "瀹氭椂浠诲姟", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{jobIds}")
+    public AjaxResult remove(@PathVariable Long[] jobIds) throws SchedulerException, TaskException
+    {
+        jobService.deleteJobByIds(jobIds);
+        return success();
+    }
+}
diff --git a/jcdm-quartz/src/main/java/com/jcdm/quartz/controller/SysJobLogController.java b/jcdm-quartz/src/main/java/com/jcdm/quartz/controller/SysJobLogController.java
new file mode 100644
index 0000000..bce16e3
--- /dev/null
+++ b/jcdm-quartz/src/main/java/com/jcdm/quartz/controller/SysJobLogController.java
@@ -0,0 +1,92 @@
+package com.jcdm.quartz.controller;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jcdm.common.annotation.Log;
+import com.jcdm.common.core.controller.BaseController;
+import com.jcdm.common.core.domain.AjaxResult;
+import com.jcdm.common.core.page.TableDataInfo;
+import com.jcdm.common.enums.BusinessType;
+import com.jcdm.common.utils.poi.ExcelUtil;
+import com.jcdm.quartz.domain.SysJobLog;
+import com.jcdm.quartz.service.ISysJobLogService;
+
+/**
+ * 璋冨害鏃ュ織鎿嶄綔澶勭悊
+ * 
+ * @author jc
+ */
+@RestController
+@RequestMapping("/monitor/jobLog")
+public class SysJobLogController extends BaseController
+{
+    @Autowired
+    private ISysJobLogService jobLogService;
+
+    /**
+     * 鏌ヨ瀹氭椂浠诲姟璋冨害鏃ュ織鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('monitor:job:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(SysJobLog sysJobLog)
+    {
+        startPage();
+        List<SysJobLog> list = jobLogService.selectJobLogList(sysJobLog);
+        return getDataTable(list);
+    }
+
+    /**
+     * 瀵煎嚭瀹氭椂浠诲姟璋冨害鏃ュ織鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('monitor:job:export')")
+    @Log(title = "浠诲姟璋冨害鏃ュ織", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, SysJobLog sysJobLog)
+    {
+        List<SysJobLog> list = jobLogService.selectJobLogList(sysJobLog);
+        ExcelUtil<SysJobLog> util = new ExcelUtil<SysJobLog>(SysJobLog.class);
+        util.exportExcel(response, list, "璋冨害鏃ュ織");
+    }
+    
+    /**
+     * 鏍规嵁璋冨害缂栧彿鑾峰彇璇︾粏淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('monitor:job:query')")
+    @GetMapping(value = "/{jobLogId}")
+    public AjaxResult getInfo(@PathVariable Long jobLogId)
+    {
+        return success(jobLogService.selectJobLogById(jobLogId));
+    }
+
+
+    /**
+     * 鍒犻櫎瀹氭椂浠诲姟璋冨害鏃ュ織
+     */
+    @PreAuthorize("@ss.hasPermi('monitor:job:remove')")
+    @Log(title = "瀹氭椂浠诲姟璋冨害鏃ュ織", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{jobLogIds}")
+    public AjaxResult remove(@PathVariable Long[] jobLogIds)
+    {
+        return toAjax(jobLogService.deleteJobLogByIds(jobLogIds));
+    }
+
+    /**
+     * 娓呯┖瀹氭椂浠诲姟璋冨害鏃ュ織
+     */
+    @PreAuthorize("@ss.hasPermi('monitor:job:remove')")
+    @Log(title = "璋冨害鏃ュ織", businessType = BusinessType.CLEAN)
+    @DeleteMapping("/clean")
+    public AjaxResult clean()
+    {
+        jobLogService.cleanJobLog();
+        return success();
+    }
+}
diff --git a/jcdm-quartz/src/main/java/com/jcdm/quartz/domain/SysJob.java b/jcdm-quartz/src/main/java/com/jcdm/quartz/domain/SysJob.java
new file mode 100644
index 0000000..d8090f3
--- /dev/null
+++ b/jcdm-quartz/src/main/java/com/jcdm/quartz/domain/SysJob.java
@@ -0,0 +1,171 @@
+package com.jcdm.quartz.domain;
+
+import java.util.Date;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Size;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.annotation.Excel.ColumnType;
+import com.jcdm.common.constant.ScheduleConstants;
+import com.jcdm.common.core.domain.BaseEntity;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.quartz.util.CronUtils;
+
+/**
+ * 瀹氭椂浠诲姟璋冨害琛� sys_job
+ * 
+ * @author jc
+ */
+public class SysJob extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 浠诲姟ID */
+    @Excel(name = "浠诲姟搴忓彿", cellType = ColumnType.NUMERIC)
+    private Long jobId;
+
+    /** 浠诲姟鍚嶇О */
+    @Excel(name = "浠诲姟鍚嶇О")
+    private String jobName;
+
+    /** 浠诲姟缁勫悕 */
+    @Excel(name = "浠诲姟缁勫悕")
+    private String jobGroup;
+
+    /** 璋冪敤鐩爣瀛楃涓� */
+    @Excel(name = "璋冪敤鐩爣瀛楃涓�")
+    private String invokeTarget;
+
+    /** cron鎵ц琛ㄨ揪寮� */
+    @Excel(name = "鎵ц琛ㄨ揪寮� ")
+    private String cronExpression;
+
+    /** cron璁″垝绛栫暐 */
+    @Excel(name = "璁″垝绛栫暐 ", readConverterExp = "0=榛樿,1=绔嬪嵆瑙﹀彂鎵ц,2=瑙﹀彂涓�娆℃墽琛�,3=涓嶈Е鍙戠珛鍗虫墽琛�")
+    private String misfirePolicy = ScheduleConstants.MISFIRE_DEFAULT;
+
+    /** 鏄惁骞跺彂鎵ц锛�0鍏佽 1绂佹锛� */
+    @Excel(name = "骞跺彂鎵ц", readConverterExp = "0=鍏佽,1=绂佹")
+    private String concurrent;
+
+    /** 浠诲姟鐘舵�侊紙0姝e父 1鏆傚仠锛� */
+    @Excel(name = "浠诲姟鐘舵��", readConverterExp = "0=姝e父,1=鏆傚仠")
+    private String status;
+
+    public Long getJobId()
+    {
+        return jobId;
+    }
+
+    public void setJobId(Long jobId)
+    {
+        this.jobId = jobId;
+    }
+
+    @NotBlank(message = "浠诲姟鍚嶇О涓嶈兘涓虹┖")
+    @Size(min = 0, max = 64, message = "浠诲姟鍚嶇О涓嶈兘瓒呰繃64涓瓧绗�")
+    public String getJobName()
+    {
+        return jobName;
+    }
+
+    public void setJobName(String jobName)
+    {
+        this.jobName = jobName;
+    }
+
+    public String getJobGroup()
+    {
+        return jobGroup;
+    }
+
+    public void setJobGroup(String jobGroup)
+    {
+        this.jobGroup = jobGroup;
+    }
+
+    @NotBlank(message = "璋冪敤鐩爣瀛楃涓蹭笉鑳戒负绌�")
+    @Size(min = 0, max = 500, message = "璋冪敤鐩爣瀛楃涓查暱搴︿笉鑳借秴杩�500涓瓧绗�")
+    public String getInvokeTarget()
+    {
+        return invokeTarget;
+    }
+
+    public void setInvokeTarget(String invokeTarget)
+    {
+        this.invokeTarget = invokeTarget;
+    }
+
+    @NotBlank(message = "Cron鎵ц琛ㄨ揪寮忎笉鑳戒负绌�")
+    @Size(min = 0, max = 255, message = "Cron鎵ц琛ㄨ揪寮忎笉鑳借秴杩�255涓瓧绗�")
+    public String getCronExpression()
+    {
+        return cronExpression;
+    }
+
+    public void setCronExpression(String cronExpression)
+    {
+        this.cronExpression = cronExpression;
+    }
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    public Date getNextValidTime()
+    {
+        if (StringUtils.isNotEmpty(cronExpression))
+        {
+            return CronUtils.getNextExecution(cronExpression);
+        }
+        return null;
+    }
+
+    public String getMisfirePolicy()
+    {
+        return misfirePolicy;
+    }
+
+    public void setMisfirePolicy(String misfirePolicy)
+    {
+        this.misfirePolicy = misfirePolicy;
+    }
+
+    public String getConcurrent()
+    {
+        return concurrent;
+    }
+
+    public void setConcurrent(String concurrent)
+    {
+        this.concurrent = concurrent;
+    }
+
+    public String getStatus()
+    {
+        return status;
+    }
+
+    public void setStatus(String status)
+    {
+        this.status = status;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("jobId", getJobId())
+            .append("jobName", getJobName())
+            .append("jobGroup", getJobGroup())
+            .append("cronExpression", getCronExpression())
+            .append("nextValidTime", getNextValidTime())
+            .append("misfirePolicy", getMisfirePolicy())
+            .append("concurrent", getConcurrent())
+            .append("status", getStatus())
+            .append("createBy", getCreateBy())
+            .append("createTime", getCreateTime())
+            .append("updateBy", getUpdateBy())
+            .append("updateTime", getUpdateTime())
+            .append("remark", getRemark())
+            .toString();
+    }
+}
diff --git a/jcdm-quartz/src/main/java/com/jcdm/quartz/domain/SysJobLog.java b/jcdm-quartz/src/main/java/com/jcdm/quartz/domain/SysJobLog.java
new file mode 100644
index 0000000..9361845
--- /dev/null
+++ b/jcdm-quartz/src/main/java/com/jcdm/quartz/domain/SysJobLog.java
@@ -0,0 +1,155 @@
+package com.jcdm.quartz.domain;
+
+import java.util.Date;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.core.domain.BaseEntity;
+
+/**
+ * 瀹氭椂浠诲姟璋冨害鏃ュ織琛� sys_job_log
+ * 
+ * @author jc
+ */
+public class SysJobLog extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** ID */
+    @Excel(name = "鏃ュ織搴忓彿")
+    private Long jobLogId;
+
+    /** 浠诲姟鍚嶇О */
+    @Excel(name = "浠诲姟鍚嶇О")
+    private String jobName;
+
+    /** 浠诲姟缁勫悕 */
+    @Excel(name = "浠诲姟缁勫悕")
+    private String jobGroup;
+
+    /** 璋冪敤鐩爣瀛楃涓� */
+    @Excel(name = "璋冪敤鐩爣瀛楃涓�")
+    private String invokeTarget;
+
+    /** 鏃ュ織淇℃伅 */
+    @Excel(name = "鏃ュ織淇℃伅")
+    private String jobMessage;
+
+    /** 鎵ц鐘舵�侊紙0姝e父 1澶辫触锛� */
+    @Excel(name = "鎵ц鐘舵��", readConverterExp = "0=姝e父,1=澶辫触")
+    private String status;
+
+    /** 寮傚父淇℃伅 */
+    @Excel(name = "寮傚父淇℃伅")
+    private String exceptionInfo;
+
+    /** 寮�濮嬫椂闂� */
+    private Date startTime;
+
+    /** 鍋滄鏃堕棿 */
+    private Date stopTime;
+
+    public Long getJobLogId()
+    {
+        return jobLogId;
+    }
+
+    public void setJobLogId(Long jobLogId)
+    {
+        this.jobLogId = jobLogId;
+    }
+
+    public String getJobName()
+    {
+        return jobName;
+    }
+
+    public void setJobName(String jobName)
+    {
+        this.jobName = jobName;
+    }
+
+    public String getJobGroup()
+    {
+        return jobGroup;
+    }
+
+    public void setJobGroup(String jobGroup)
+    {
+        this.jobGroup = jobGroup;
+    }
+
+    public String getInvokeTarget()
+    {
+        return invokeTarget;
+    }
+
+    public void setInvokeTarget(String invokeTarget)
+    {
+        this.invokeTarget = invokeTarget;
+    }
+
+    public String getJobMessage()
+    {
+        return jobMessage;
+    }
+
+    public void setJobMessage(String jobMessage)
+    {
+        this.jobMessage = jobMessage;
+    }
+
+    public String getStatus()
+    {
+        return status;
+    }
+
+    public void setStatus(String status)
+    {
+        this.status = status;
+    }
+
+    public String getExceptionInfo()
+    {
+        return exceptionInfo;
+    }
+
+    public void setExceptionInfo(String exceptionInfo)
+    {
+        this.exceptionInfo = exceptionInfo;
+    }
+
+    public Date getStartTime()
+    {
+        return startTime;
+    }
+
+    public void setStartTime(Date startTime)
+    {
+        this.startTime = startTime;
+    }
+    
+    public Date getStopTime()
+    {
+        return stopTime;
+    }
+
+    public void setStopTime(Date stopTime)
+    {
+        this.stopTime = stopTime;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("jobLogId", getJobLogId())
+            .append("jobName", getJobName())
+            .append("jobGroup", getJobGroup())
+            .append("jobMessage", getJobMessage())
+            .append("status", getStatus())
+            .append("exceptionInfo", getExceptionInfo())
+            .append("startTime", getStartTime())
+            .append("stopTime", getStopTime())
+            .toString();
+    }
+}
diff --git a/jcdm-quartz/src/main/java/com/jcdm/quartz/mapper/SysJobLogMapper.java b/jcdm-quartz/src/main/java/com/jcdm/quartz/mapper/SysJobLogMapper.java
new file mode 100644
index 0000000..842035c
--- /dev/null
+++ b/jcdm-quartz/src/main/java/com/jcdm/quartz/mapper/SysJobLogMapper.java
@@ -0,0 +1,64 @@
+package com.jcdm.quartz.mapper;
+
+import java.util.List;
+import com.jcdm.quartz.domain.SysJobLog;
+
+/**
+ * 璋冨害浠诲姟鏃ュ織淇℃伅 鏁版嵁灞�
+ * 
+ * @author jc
+ */
+public interface SysJobLogMapper
+{
+    /**
+     * 鑾峰彇quartz璋冨害鍣ㄦ棩蹇楃殑璁″垝浠诲姟
+     * 
+     * @param jobLog 璋冨害鏃ュ織淇℃伅
+     * @return 璋冨害浠诲姟鏃ュ織闆嗗悎
+     */
+    public List<SysJobLog> selectJobLogList(SysJobLog jobLog);
+
+    /**
+     * 鏌ヨ鎵�鏈夎皟搴︿换鍔℃棩蹇�
+     *
+     * @return 璋冨害浠诲姟鏃ュ織鍒楄〃
+     */
+    public List<SysJobLog> selectJobLogAll();
+
+    /**
+     * 閫氳繃璋冨害浠诲姟鏃ュ織ID鏌ヨ璋冨害淇℃伅
+     * 
+     * @param jobLogId 璋冨害浠诲姟鏃ュ織ID
+     * @return 璋冨害浠诲姟鏃ュ織瀵硅薄淇℃伅
+     */
+    public SysJobLog selectJobLogById(Long jobLogId);
+
+    /**
+     * 鏂板浠诲姟鏃ュ織
+     * 
+     * @param jobLog 璋冨害鏃ュ織淇℃伅
+     * @return 缁撴灉
+     */
+    public int insertJobLog(SysJobLog jobLog);
+
+    /**
+     * 鎵归噺鍒犻櫎璋冨害鏃ュ織淇℃伅
+     * 
+     * @param logIds 闇�瑕佸垹闄ょ殑鏁版嵁ID
+     * @return 缁撴灉
+     */
+    public int deleteJobLogByIds(Long[] logIds);
+
+    /**
+     * 鍒犻櫎浠诲姟鏃ュ織
+     * 
+     * @param jobId 璋冨害鏃ュ織ID
+     * @return 缁撴灉
+     */
+    public int deleteJobLogById(Long jobId);
+
+    /**
+     * 娓呯┖浠诲姟鏃ュ織
+     */
+    public void cleanJobLog();
+}
diff --git a/jcdm-quartz/src/main/java/com/jcdm/quartz/mapper/SysJobMapper.java b/jcdm-quartz/src/main/java/com/jcdm/quartz/mapper/SysJobMapper.java
new file mode 100644
index 0000000..88f1b18
--- /dev/null
+++ b/jcdm-quartz/src/main/java/com/jcdm/quartz/mapper/SysJobMapper.java
@@ -0,0 +1,67 @@
+package com.jcdm.quartz.mapper;
+
+import java.util.List;
+import com.jcdm.quartz.domain.SysJob;
+
+/**
+ * 璋冨害浠诲姟淇℃伅 鏁版嵁灞�
+ * 
+ * @author jc
+ */
+public interface SysJobMapper
+{
+    /**
+     * 鏌ヨ璋冨害浠诲姟鏃ュ織闆嗗悎
+     * 
+     * @param job 璋冨害淇℃伅
+     * @return 鎿嶄綔鏃ュ織闆嗗悎
+     */
+    public List<SysJob> selectJobList(SysJob job);
+
+    /**
+     * 鏌ヨ鎵�鏈夎皟搴︿换鍔�
+     * 
+     * @return 璋冨害浠诲姟鍒楄〃
+     */
+    public List<SysJob> selectJobAll();
+
+    /**
+     * 閫氳繃璋冨害ID鏌ヨ璋冨害浠诲姟淇℃伅
+     * 
+     * @param jobId 璋冨害ID
+     * @return 瑙掕壊瀵硅薄淇℃伅
+     */
+    public SysJob selectJobById(Long jobId);
+
+    /**
+     * 閫氳繃璋冨害ID鍒犻櫎璋冨害浠诲姟淇℃伅
+     * 
+     * @param jobId 璋冨害ID
+     * @return 缁撴灉
+     */
+    public int deleteJobById(Long jobId);
+
+    /**
+     * 鎵归噺鍒犻櫎璋冨害浠诲姟淇℃伅
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁ID
+     * @return 缁撴灉
+     */
+    public int deleteJobByIds(Long[] ids);
+
+    /**
+     * 淇敼璋冨害浠诲姟淇℃伅
+     * 
+     * @param job 璋冨害浠诲姟淇℃伅
+     * @return 缁撴灉
+     */
+    public int updateJob(SysJob job);
+
+    /**
+     * 鏂板璋冨害浠诲姟淇℃伅
+     * 
+     * @param job 璋冨害浠诲姟淇℃伅
+     * @return 缁撴灉
+     */
+    public int insertJob(SysJob job);
+}
diff --git a/jcdm-quartz/src/main/java/com/jcdm/quartz/service/ISysJobLogService.java b/jcdm-quartz/src/main/java/com/jcdm/quartz/service/ISysJobLogService.java
new file mode 100644
index 0000000..15c07aa
--- /dev/null
+++ b/jcdm-quartz/src/main/java/com/jcdm/quartz/service/ISysJobLogService.java
@@ -0,0 +1,56 @@
+package com.jcdm.quartz.service;
+
+import java.util.List;
+import com.jcdm.quartz.domain.SysJobLog;
+
+/**
+ * 瀹氭椂浠诲姟璋冨害鏃ュ織淇℃伅淇℃伅 鏈嶅姟灞�
+ * 
+ * @author jc
+ */
+public interface ISysJobLogService
+{
+    /**
+     * 鑾峰彇quartz璋冨害鍣ㄦ棩蹇楃殑璁″垝浠诲姟
+     * 
+     * @param jobLog 璋冨害鏃ュ織淇℃伅
+     * @return 璋冨害浠诲姟鏃ュ織闆嗗悎
+     */
+    public List<SysJobLog> selectJobLogList(SysJobLog jobLog);
+
+    /**
+     * 閫氳繃璋冨害浠诲姟鏃ュ織ID鏌ヨ璋冨害淇℃伅
+     * 
+     * @param jobLogId 璋冨害浠诲姟鏃ュ織ID
+     * @return 璋冨害浠诲姟鏃ュ織瀵硅薄淇℃伅
+     */
+    public SysJobLog selectJobLogById(Long jobLogId);
+
+    /**
+     * 鏂板浠诲姟鏃ュ織
+     * 
+     * @param jobLog 璋冨害鏃ュ織淇℃伅
+     */
+    public void addJobLog(SysJobLog jobLog);
+
+    /**
+     * 鎵归噺鍒犻櫎璋冨害鏃ュ織淇℃伅
+     * 
+     * @param logIds 闇�瑕佸垹闄ょ殑鏃ュ織ID
+     * @return 缁撴灉
+     */
+    public int deleteJobLogByIds(Long[] logIds);
+
+    /**
+     * 鍒犻櫎浠诲姟鏃ュ織
+     * 
+     * @param jobId 璋冨害鏃ュ織ID
+     * @return 缁撴灉
+     */
+    public int deleteJobLogById(Long jobId);
+
+    /**
+     * 娓呯┖浠诲姟鏃ュ織
+     */
+    public void cleanJobLog();
+}
diff --git a/jcdm-quartz/src/main/java/com/jcdm/quartz/service/ISysJobService.java b/jcdm-quartz/src/main/java/com/jcdm/quartz/service/ISysJobService.java
new file mode 100644
index 0000000..cdf1cba
--- /dev/null
+++ b/jcdm-quartz/src/main/java/com/jcdm/quartz/service/ISysJobService.java
@@ -0,0 +1,102 @@
+package com.jcdm.quartz.service;
+
+import java.util.List;
+import org.quartz.SchedulerException;
+import com.jcdm.common.exception.job.TaskException;
+import com.jcdm.quartz.domain.SysJob;
+
+/**
+ * 瀹氭椂浠诲姟璋冨害淇℃伅淇℃伅 鏈嶅姟灞�
+ * 
+ * @author jc
+ */
+public interface ISysJobService
+{
+    /**
+     * 鑾峰彇quartz璋冨害鍣ㄧ殑璁″垝浠诲姟
+     * 
+     * @param job 璋冨害淇℃伅
+     * @return 璋冨害浠诲姟闆嗗悎
+     */
+    public List<SysJob> selectJobList(SysJob job);
+
+    /**
+     * 閫氳繃璋冨害浠诲姟ID鏌ヨ璋冨害淇℃伅
+     * 
+     * @param jobId 璋冨害浠诲姟ID
+     * @return 璋冨害浠诲姟瀵硅薄淇℃伅
+     */
+    public SysJob selectJobById(Long jobId);
+
+    /**
+     * 鏆傚仠浠诲姟
+     * 
+     * @param job 璋冨害淇℃伅
+     * @return 缁撴灉
+     */
+    public int pauseJob(SysJob job) throws SchedulerException;
+
+    /**
+     * 鎭㈠浠诲姟
+     * 
+     * @param job 璋冨害淇℃伅
+     * @return 缁撴灉
+     */
+    public int resumeJob(SysJob job) throws SchedulerException;
+
+    /**
+     * 鍒犻櫎浠诲姟鍚庯紝鎵�瀵瑰簲鐨則rigger涔熷皢琚垹闄�
+     * 
+     * @param job 璋冨害淇℃伅
+     * @return 缁撴灉
+     */
+    public int deleteJob(SysJob job) throws SchedulerException;
+
+    /**
+     * 鎵归噺鍒犻櫎璋冨害淇℃伅
+     * 
+     * @param jobIds 闇�瑕佸垹闄ょ殑浠诲姟ID
+     * @return 缁撴灉
+     */
+    public void deleteJobByIds(Long[] jobIds) throws SchedulerException;
+
+    /**
+     * 浠诲姟璋冨害鐘舵�佷慨鏀�
+     * 
+     * @param job 璋冨害淇℃伅
+     * @return 缁撴灉
+     */
+    public int changeStatus(SysJob job) throws SchedulerException;
+
+    /**
+     * 绔嬪嵆杩愯浠诲姟
+     * 
+     * @param job 璋冨害淇℃伅
+     * @return 缁撴灉
+     */
+    public boolean run(SysJob job) throws SchedulerException;
+
+    /**
+     * 鏂板浠诲姟
+     * 
+     * @param job 璋冨害淇℃伅
+     * @return 缁撴灉
+     */
+    public int insertJob(SysJob job) throws SchedulerException, TaskException;
+
+    /**
+     * 鏇存柊浠诲姟
+     * 
+     * @param job 璋冨害淇℃伅
+     * @return 缁撴灉
+     */
+    public int updateJob(SysJob job) throws SchedulerException, TaskException;
+
+    /**
+     * 鏍¢獙cron琛ㄨ揪寮忔槸鍚︽湁鏁�
+     * 
+     * @param cronExpression 琛ㄨ揪寮�
+     * @return 缁撴灉
+     */
+    public boolean checkCronExpressionIsValid(String cronExpression);
+}
diff --git a/jcdm-quartz/src/main/java/com/jcdm/quartz/service/impl/SysJobLogServiceImpl.java b/jcdm-quartz/src/main/java/com/jcdm/quartz/service/impl/SysJobLogServiceImpl.java
new file mode 100644
index 0000000..932dff8
--- /dev/null
+++ b/jcdm-quartz/src/main/java/com/jcdm/quartz/service/impl/SysJobLogServiceImpl.java
@@ -0,0 +1,87 @@
+package com.jcdm.quartz.service.impl;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.jcdm.quartz.domain.SysJobLog;
+import com.jcdm.quartz.mapper.SysJobLogMapper;
+import com.jcdm.quartz.service.ISysJobLogService;
+
+/**
+ * 瀹氭椂浠诲姟璋冨害鏃ュ織淇℃伅 鏈嶅姟灞�
+ * 
+ * @author jc
+ */
+@Service
+public class SysJobLogServiceImpl implements ISysJobLogService
+{
+    @Autowired
+    private SysJobLogMapper jobLogMapper;
+
+    /**
+     * 鑾峰彇quartz璋冨害鍣ㄦ棩蹇楃殑璁″垝浠诲姟
+     * 
+     * @param jobLog 璋冨害鏃ュ織淇℃伅
+     * @return 璋冨害浠诲姟鏃ュ織闆嗗悎
+     */
+    @Override
+    public List<SysJobLog> selectJobLogList(SysJobLog jobLog)
+    {
+        return jobLogMapper.selectJobLogList(jobLog);
+    }
+
+    /**
+     * 閫氳繃璋冨害浠诲姟鏃ュ織ID鏌ヨ璋冨害淇℃伅
+     * 
+     * @param jobLogId 璋冨害浠诲姟鏃ュ織ID
+     * @return 璋冨害浠诲姟鏃ュ織瀵硅薄淇℃伅
+     */
+    @Override
+    public SysJobLog selectJobLogById(Long jobLogId)
+    {
+        return jobLogMapper.selectJobLogById(jobLogId);
+    }
+
+    /**
+     * 鏂板浠诲姟鏃ュ織
+     * 
+     * @param jobLog 璋冨害鏃ュ織淇℃伅
+     */
+    @Override
+    public void addJobLog(SysJobLog jobLog)
+    {
+        jobLogMapper.insertJobLog(jobLog);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎璋冨害鏃ュ織淇℃伅
+     * 
+     * @param logIds 闇�瑕佸垹闄ょ殑鏁版嵁ID
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteJobLogByIds(Long[] logIds)
+    {
+        return jobLogMapper.deleteJobLogByIds(logIds);
+    }
+
+    /**
+     * 鍒犻櫎浠诲姟鏃ュ織
+     * 
+     * @param jobId 璋冨害鏃ュ織ID
+     */
+    @Override
+    public int deleteJobLogById(Long jobId)
+    {
+        return jobLogMapper.deleteJobLogById(jobId);
+    }
+
+    /**
+     * 娓呯┖浠诲姟鏃ュ織
+     */
+    @Override
+    public void cleanJobLog()
+    {
+        jobLogMapper.cleanJobLog();
+    }
+}
diff --git a/jcdm-quartz/src/main/java/com/jcdm/quartz/service/impl/SysJobServiceImpl.java b/jcdm-quartz/src/main/java/com/jcdm/quartz/service/impl/SysJobServiceImpl.java
new file mode 100644
index 0000000..65c20aa
--- /dev/null
+++ b/jcdm-quartz/src/main/java/com/jcdm/quartz/service/impl/SysJobServiceImpl.java
@@ -0,0 +1,261 @@
+package com.jcdm.quartz.service.impl;
+
+import java.util.List;
+import javax.annotation.PostConstruct;
+import org.quartz.JobDataMap;
+import org.quartz.JobKey;
+import org.quartz.Scheduler;
+import org.quartz.SchedulerException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import com.jcdm.common.constant.ScheduleConstants;
+import com.jcdm.common.exception.job.TaskException;
+import com.jcdm.quartz.domain.SysJob;
+import com.jcdm.quartz.mapper.SysJobMapper;
+import com.jcdm.quartz.service.ISysJobService;
+import com.jcdm.quartz.util.CronUtils;
+import com.jcdm.quartz.util.ScheduleUtils;
+
+/**
+ * 瀹氭椂浠诲姟璋冨害淇℃伅 鏈嶅姟灞�
+ * 
+ * @author jc
+ */
+@Service
+public class SysJobServiceImpl implements ISysJobService
+{
+    @Autowired
+    private Scheduler scheduler;
+
+    @Autowired
+    private SysJobMapper jobMapper;
+
+    /**
+     * 椤圭洰鍚姩鏃讹紝鍒濆鍖栧畾鏃跺櫒 涓昏鏄槻姝㈡墜鍔ㄤ慨鏀规暟鎹簱瀵艰嚧鏈悓姝ュ埌瀹氭椂浠诲姟澶勭悊锛堟敞锛氫笉鑳芥墜鍔ㄤ慨鏀规暟鎹簱ID鍜屼换鍔$粍鍚嶏紝鍚﹀垯浼氬鑷磋剰鏁版嵁锛�
+     */
+    @PostConstruct
+    public void init() throws SchedulerException, TaskException
+    {
+        scheduler.clear();
+        List<SysJob> jobList = jobMapper.selectJobAll();
+        for (SysJob job : jobList)
+        {
+            ScheduleUtils.createScheduleJob(scheduler, job);
+        }
+    }
+
+    /**
+     * 鑾峰彇quartz璋冨害鍣ㄧ殑璁″垝浠诲姟鍒楄〃
+     * 
+     * @param job 璋冨害淇℃伅
+     * @return
+     */
+    @Override
+    public List<SysJob> selectJobList(SysJob job)
+    {
+        return jobMapper.selectJobList(job);
+    }
+
+    /**
+     * 閫氳繃璋冨害浠诲姟ID鏌ヨ璋冨害淇℃伅
+     * 
+     * @param jobId 璋冨害浠诲姟ID
+     * @return 璋冨害浠诲姟瀵硅薄淇℃伅
+     */
+    @Override
+    public SysJob selectJobById(Long jobId)
+    {
+        return jobMapper.selectJobById(jobId);
+    }
+
+    /**
+     * 鏆傚仠浠诲姟
+     * 
+     * @param job 璋冨害淇℃伅
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int pauseJob(SysJob job) throws SchedulerException
+    {
+        Long jobId = job.getJobId();
+        String jobGroup = job.getJobGroup();
+        job.setStatus(ScheduleConstants.Status.PAUSE.getValue());
+        int rows = jobMapper.updateJob(job);
+        if (rows > 0)
+        {
+            scheduler.pauseJob(ScheduleUtils.getJobKey(jobId, jobGroup));
+        }
+        return rows;
+    }
+
+    /**
+     * 鎭㈠浠诲姟
+     * 
+     * @param job 璋冨害淇℃伅
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int resumeJob(SysJob job) throws SchedulerException
+    {
+        Long jobId = job.getJobId();
+        String jobGroup = job.getJobGroup();
+        job.setStatus(ScheduleConstants.Status.NORMAL.getValue());
+        int rows = jobMapper.updateJob(job);
+        if (rows > 0)
+        {
+            scheduler.resumeJob(ScheduleUtils.getJobKey(jobId, jobGroup));
+        }
+        return rows;
+    }
+
+    /**
+     * 鍒犻櫎浠诲姟鍚庯紝鎵�瀵瑰簲鐨則rigger涔熷皢琚垹闄�
+     * 
+     * @param job 璋冨害淇℃伅
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int deleteJob(SysJob job) throws SchedulerException
+    {
+        Long jobId = job.getJobId();
+        String jobGroup = job.getJobGroup();
+        int rows = jobMapper.deleteJobById(jobId);
+        if (rows > 0)
+        {
+            scheduler.deleteJob(ScheduleUtils.getJobKey(jobId, jobGroup));
+        }
+        return rows;
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎璋冨害淇℃伅
+     * 
+     * @param jobIds 闇�瑕佸垹闄ょ殑浠诲姟ID
+     * @return 缁撴灉
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void deleteJobByIds(Long[] jobIds) throws SchedulerException
+    {
+        for (Long jobId : jobIds)
+        {
+            SysJob job = jobMapper.selectJobById(jobId);
+            deleteJob(job);
+        }
+    }
+
+    /**
+     * 浠诲姟璋冨害鐘舵�佷慨鏀�
+     * 
+     * @param job 璋冨害淇℃伅
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int changeStatus(SysJob job) throws SchedulerException
+    {
+        int rows = 0;
+        String status = job.getStatus();
+        if (ScheduleConstants.Status.NORMAL.getValue().equals(status))
+        {
+            rows = resumeJob(job);
+        }
+        else if (ScheduleConstants.Status.PAUSE.getValue().equals(status))
+        {
+            rows = pauseJob(job);
+        }
+        return rows;
+    }
+
+    /**
+     * 绔嬪嵆杩愯浠诲姟
+     * 
+     * @param job 璋冨害淇℃伅
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean run(SysJob job) throws SchedulerException
+    {
+        boolean result = false;
+        Long jobId = job.getJobId();
+        String jobGroup = job.getJobGroup();
+        SysJob properties = selectJobById(job.getJobId());
+        // 鍙傛暟
+        JobDataMap dataMap = new JobDataMap();
+        dataMap.put(ScheduleConstants.TASK_PROPERTIES, properties);
+        JobKey jobKey = ScheduleUtils.getJobKey(jobId, jobGroup);
+        if (scheduler.checkExists(jobKey))
+        {
+            result = true;
+            scheduler.triggerJob(jobKey, dataMap);
+        }
+        return result;
+    }
+
+    /**
+     * 鏂板浠诲姟
+     * 
+     * @param job 璋冨害淇℃伅 璋冨害淇℃伅
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int insertJob(SysJob job) throws SchedulerException, TaskException
+    {
+        job.setStatus(ScheduleConstants.Status.PAUSE.getValue());
+        int rows = jobMapper.insertJob(job);
+        if (rows > 0)
+        {
+            ScheduleUtils.createScheduleJob(scheduler, job);
+        }
+        return rows;
+    }
+
+    /**
+     * 鏇存柊浠诲姟鐨勬椂闂磋〃杈惧紡
+     * 
+     * @param job 璋冨害淇℃伅
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int updateJob(SysJob job) throws SchedulerException, TaskException
+    {
+        SysJob properties = selectJobById(job.getJobId());
+        int rows = jobMapper.updateJob(job);
+        if (rows > 0)
+        {
+            updateSchedulerJob(job, properties.getJobGroup());
+        }
+        return rows;
+    }
+
+    /**
+     * 鏇存柊浠诲姟
+     * 
+     * @param job 浠诲姟瀵硅薄
+     * @param jobGroup 浠诲姟缁勫悕
+     */
+    public void updateSchedulerJob(SysJob job, String jobGroup) throws SchedulerException, TaskException
+    {
+        Long jobId = job.getJobId();
+        // 鍒ゆ柇鏄惁瀛樺湪
+        JobKey jobKey = ScheduleUtils.getJobKey(jobId, jobGroup);
+        if (scheduler.checkExists(jobKey))
+        {
+            // 闃叉鍒涘缓鏃跺瓨鍦ㄦ暟鎹棶棰� 鍏堢Щ闄わ紝鐒跺悗鍦ㄦ墽琛屽垱寤烘搷浣�
+            scheduler.deleteJob(jobKey);
+        }
+        ScheduleUtils.createScheduleJob(scheduler, job);
+    }
+
+    /**
+     * 鏍¢獙cron琛ㄨ揪寮忔槸鍚︽湁鏁�
+     * 
+     * @param cronExpression 琛ㄨ揪寮�
+     * @return 缁撴灉
+     */
+    @Override
+    public boolean checkCronExpressionIsValid(String cronExpression)
+    {
+        return CronUtils.isValid(cronExpression);
+    }
+}
diff --git a/jcdm-quartz/src/main/java/com/jcdm/quartz/task/RyTask.java b/jcdm-quartz/src/main/java/com/jcdm/quartz/task/RyTask.java
new file mode 100644
index 0000000..d0f1e89
--- /dev/null
+++ b/jcdm-quartz/src/main/java/com/jcdm/quartz/task/RyTask.java
@@ -0,0 +1,28 @@
+package com.jcdm.quartz.task;
+
+import org.springframework.stereotype.Component;
+import com.jcdm.common.utils.StringUtils;
+
+/**
+ * 瀹氭椂浠诲姟璋冨害娴嬭瘯
+ * 
+ * @author jc
+ */
+@Component("ryTask")
+public class RyTask
+{
+    public void ryMultipleParams(String s, Boolean b, Long l, Double d, Integer i)
+    {
+        System.out.println(StringUtils.format("鎵ц澶氬弬鏂规硶锛� 瀛楃涓茬被鍨媨}锛屽竷灏旂被鍨媨}锛岄暱鏁村瀷{}锛屾诞鐐瑰瀷{}锛屾暣褰}", s, b, l, d, i));
+    }
+
+    public void ryParams(String params)
+    {
+        System.out.println("鎵ц鏈夊弬鏂规硶锛�" + params);
+    }
+
+    public void ryNoParams()
+    {
+        System.out.println("鎵ц鏃犲弬鏂规硶");
+    }
+}
diff --git a/jcdm-quartz/src/main/java/com/jcdm/quartz/util/AbstractQuartzJob.java b/jcdm-quartz/src/main/java/com/jcdm/quartz/util/AbstractQuartzJob.java
new file mode 100644
index 0000000..8eb17fb
--- /dev/null
+++ b/jcdm-quartz/src/main/java/com/jcdm/quartz/util/AbstractQuartzJob.java
@@ -0,0 +1,107 @@
+package com.jcdm.quartz.util;
+
+import java.util.Date;
+import org.quartz.Job;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.jcdm.common.constant.Constants;
+import com.jcdm.common.constant.ScheduleConstants;
+import com.jcdm.common.utils.ExceptionUtil;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.common.utils.bean.BeanUtils;
+import com.jcdm.common.utils.spring.SpringUtils;
+import com.jcdm.quartz.domain.SysJob;
+import com.jcdm.quartz.domain.SysJobLog;
+import com.jcdm.quartz.service.ISysJobLogService;
+
+/**
+ * 鎶借薄quartz璋冪敤
+ *
+ * @author jc
+ */
+public abstract class AbstractQuartzJob implements Job
+{
+    private static final Logger log = LoggerFactory.getLogger(AbstractQuartzJob.class);
+
+    /**
+     * 绾跨▼鏈湴鍙橀噺
+     */
+    private static ThreadLocal<Date> threadLocal = new ThreadLocal<>();
+
+    @Override
+    public void execute(JobExecutionContext context) throws JobExecutionException
+    {
+        SysJob sysJob = new SysJob();
+        BeanUtils.copyBeanProp(sysJob, context.getMergedJobDataMap().get(ScheduleConstants.TASK_PROPERTIES));
+        try
+        {
+            before(context, sysJob);
+            if (sysJob != null)
+            {
+                doExecute(context, sysJob);
+            }
+            after(context, sysJob, null);
+        }
+        catch (Exception e)
+        {
+            log.error("浠诲姟鎵ц寮傚父  - 锛�", e);
+            after(context, sysJob, e);
+        }
+    }
+
+    /**
+     * 鎵ц鍓�
+     *
+     * @param context 宸ヤ綔鎵ц涓婁笅鏂囧璞�
+     * @param sysJob 绯荤粺璁″垝浠诲姟
+     */
+    protected void before(JobExecutionContext context, SysJob sysJob)
+    {
+        threadLocal.set(new Date());
+    }
+
+    /**
+     * 鎵ц鍚�
+     *
+     * @param context 宸ヤ綔鎵ц涓婁笅鏂囧璞�
+     * @param sysJob 绯荤粺璁″垝浠诲姟
+     */
+    protected void after(JobExecutionContext context, SysJob sysJob, Exception e)
+    {
+        Date startTime = threadLocal.get();
+        threadLocal.remove();
+
+        final SysJobLog sysJobLog = new SysJobLog();
+        sysJobLog.setJobName(sysJob.getJobName());
+        sysJobLog.setJobGroup(sysJob.getJobGroup());
+        sysJobLog.setInvokeTarget(sysJob.getInvokeTarget());
+        sysJobLog.setStartTime(startTime);
+        sysJobLog.setStopTime(new Date());
+        long runMs = sysJobLog.getStopTime().getTime() - sysJobLog.getStartTime().getTime();
+        sysJobLog.setJobMessage(sysJobLog.getJobName() + " 鎬诲叡鑰楁椂锛�" + runMs + "姣");
+        if (e != null)
+        {
+            sysJobLog.setStatus(Constants.FAIL);
+            String errorMsg = StringUtils.substring(ExceptionUtil.getExceptionMessage(e), 0, 2000);
+            sysJobLog.setExceptionInfo(errorMsg);
+        }
+        else
+        {
+            sysJobLog.setStatus(Constants.SUCCESS);
+        }
+
+        // 鍐欏叆鏁版嵁搴撳綋涓�
+        SpringUtils.getBean(ISysJobLogService.class).addJobLog(sysJobLog);
+    }
+
+    /**
+     * 鎵ц鏂规硶锛岀敱瀛愮被閲嶈浇
+     *
+     * @param context 宸ヤ綔鎵ц涓婁笅鏂囧璞�
+     * @param sysJob 绯荤粺璁″垝浠诲姟
+     * @throws Exception 鎵ц杩囩▼涓殑寮傚父
+     */
+    protected abstract void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception;
+}
diff --git a/jcdm-quartz/src/main/java/com/jcdm/quartz/util/CronUtils.java b/jcdm-quartz/src/main/java/com/jcdm/quartz/util/CronUtils.java
new file mode 100644
index 0000000..fe38ffd
--- /dev/null
+++ b/jcdm-quartz/src/main/java/com/jcdm/quartz/util/CronUtils.java
@@ -0,0 +1,63 @@
+package com.jcdm.quartz.util;
+
+import java.text.ParseException;
+import java.util.Date;
+import org.quartz.CronExpression;
+
+/**
+ * cron琛ㄨ揪寮忓伐鍏风被
+ * 
+ * @author jc
+ *
+ */
+public class CronUtils
+{
+    /**
+     * 杩斿洖涓�涓竷灏斿�间唬琛ㄤ竴涓粰瀹氱殑Cron琛ㄨ揪寮忕殑鏈夋晥鎬�
+     *
+     * @param cronExpression Cron琛ㄨ揪寮�
+     * @return boolean 琛ㄨ揪寮忔槸鍚︽湁鏁�
+     */
+    public static boolean isValid(String cronExpression)
+    {
+        return CronExpression.isValidExpression(cronExpression);
+    }
+
+    /**
+     * 杩斿洖涓�涓瓧绗︿覆鍊�,琛ㄧず璇ユ秷鎭棤鏁圕ron琛ㄨ揪寮忕粰鍑烘湁鏁堟��
+     *
+     * @param cronExpression Cron琛ㄨ揪寮�
+     * @return String 鏃犳晥鏃惰繑鍥炶〃杈惧紡閿欒鎻忚堪,濡傛灉鏈夋晥杩斿洖null
+     */
+    public static String getInvalidMessage(String cronExpression)
+    {
+        try
+        {
+            new CronExpression(cronExpression);
+            return null;
+        }
+        catch (ParseException pe)
+        {
+            return pe.getMessage();
+        }
+    }
+
+    /**
+     * 杩斿洖涓嬩竴涓墽琛屾椂闂存牴鎹粰瀹氱殑Cron琛ㄨ揪寮�
+     *
+     * @param cronExpression Cron琛ㄨ揪寮�
+     * @return Date 涓嬫Cron琛ㄨ揪寮忔墽琛屾椂闂�
+     */
+    public static Date getNextExecution(String cronExpression)
+    {
+        try
+        {
+            CronExpression cron = new CronExpression(cronExpression);
+            return cron.getNextValidTimeAfter(new Date(System.currentTimeMillis()));
+        }
+        catch (ParseException e)
+        {
+            throw new IllegalArgumentException(e.getMessage());
+        }
+    }
+}
diff --git a/jcdm-quartz/src/main/java/com/jcdm/quartz/util/JobInvokeUtil.java b/jcdm-quartz/src/main/java/com/jcdm/quartz/util/JobInvokeUtil.java
new file mode 100644
index 0000000..3e3c223
--- /dev/null
+++ b/jcdm-quartz/src/main/java/com/jcdm/quartz/util/JobInvokeUtil.java
@@ -0,0 +1,182 @@
+package com.jcdm.quartz.util;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.LinkedList;
+import java.util.List;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.common.utils.spring.SpringUtils;
+import com.jcdm.quartz.domain.SysJob;
+
+/**
+ * 浠诲姟鎵ц宸ュ叿
+ *
+ * @author jc
+ */
+public class JobInvokeUtil
+{
+    /**
+     * 鎵ц鏂规硶
+     *
+     * @param sysJob 绯荤粺浠诲姟
+     */
+    public static void invokeMethod(SysJob sysJob) throws Exception
+    {
+        String invokeTarget = sysJob.getInvokeTarget();
+        String beanName = getBeanName(invokeTarget);
+        String methodName = getMethodName(invokeTarget);
+        List<Object[]> methodParams = getMethodParams(invokeTarget);
+
+        if (!isValidClassName(beanName))
+        {
+            Object bean = SpringUtils.getBean(beanName);
+            invokeMethod(bean, methodName, methodParams);
+        }
+        else
+        {
+            Object bean = Class.forName(beanName).getDeclaredConstructor().newInstance();
+            invokeMethod(bean, methodName, methodParams);
+        }
+    }
+
+    /**
+     * 璋冪敤浠诲姟鏂规硶
+     *
+     * @param bean 鐩爣瀵硅薄
+     * @param methodName 鏂规硶鍚嶇О
+     * @param methodParams 鏂规硶鍙傛暟
+     */
+    private static void invokeMethod(Object bean, String methodName, List<Object[]> methodParams)
+            throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException,
+            InvocationTargetException
+    {
+        if (StringUtils.isNotNull(methodParams) && methodParams.size() > 0)
+        {
+            Method method = bean.getClass().getMethod(methodName, getMethodParamsType(methodParams));
+            method.invoke(bean, getMethodParamsValue(methodParams));
+        }
+        else
+        {
+            Method method = bean.getClass().getMethod(methodName);
+            method.invoke(bean);
+        }
+    }
+
+    /**
+     * 鏍¢獙鏄惁涓轰负class鍖呭悕
+     * 
+     * @param invokeTarget 鍚嶇О
+     * @return true鏄� false鍚�
+     */
+    public static boolean isValidClassName(String invokeTarget)
+    {
+        return StringUtils.countMatches(invokeTarget, ".") > 1;
+    }
+
+    /**
+     * 鑾峰彇bean鍚嶇О
+     * 
+     * @param invokeTarget 鐩爣瀛楃涓�
+     * @return bean鍚嶇О
+     */
+    public static String getBeanName(String invokeTarget)
+    {
+        String beanName = StringUtils.substringBefore(invokeTarget, "(");
+        return StringUtils.substringBeforeLast(beanName, ".");
+    }
+
+    /**
+     * 鑾峰彇bean鏂规硶
+     * 
+     * @param invokeTarget 鐩爣瀛楃涓�
+     * @return method鏂规硶
+     */
+    public static String getMethodName(String invokeTarget)
+    {
+        String methodName = StringUtils.substringBefore(invokeTarget, "(");
+        return StringUtils.substringAfterLast(methodName, ".");
+    }
+
+    /**
+     * 鑾峰彇method鏂规硶鍙傛暟鐩稿叧鍒楄〃
+     * 
+     * @param invokeTarget 鐩爣瀛楃涓�
+     * @return method鏂规硶鐩稿叧鍙傛暟鍒楄〃
+     */
+    public static List<Object[]> getMethodParams(String invokeTarget)
+    {
+        String methodStr = StringUtils.substringBetween(invokeTarget, "(", ")");
+        if (StringUtils.isEmpty(methodStr))
+        {
+            return null;
+        }
+        String[] methodParams = methodStr.split(",(?=([^\"']*[\"'][^\"']*[\"'])*[^\"']*$)");
+        List<Object[]> classs = new LinkedList<>();
+        for (int i = 0; i < methodParams.length; i++)
+        {
+            String str = StringUtils.trimToEmpty(methodParams[i]);
+            // String瀛楃涓茬被鍨嬶紝浠�'鎴�"寮�澶�
+            if (StringUtils.startsWithAny(str, "'", "\""))
+            {
+                classs.add(new Object[] { StringUtils.substring(str, 1, str.length() - 1), String.class });
+            }
+            // boolean甯冨皵绫诲瀷锛岀瓑浜巘rue鎴栬�協alse
+            else if ("true".equalsIgnoreCase(str) || "false".equalsIgnoreCase(str))
+            {
+                classs.add(new Object[] { Boolean.valueOf(str), Boolean.class });
+            }
+            // long闀挎暣褰紝浠缁撳熬
+            else if (StringUtils.endsWith(str, "L"))
+            {
+                classs.add(new Object[] { Long.valueOf(StringUtils.substring(str, 0, str.length() - 1)), Long.class });
+            }
+            // double娴偣绫诲瀷锛屼互D缁撳熬
+            else if (StringUtils.endsWith(str, "D"))
+            {
+                classs.add(new Object[] { Double.valueOf(StringUtils.substring(str, 0, str.length() - 1)), Double.class });
+            }
+            // 鍏朵粬绫诲瀷褰掔被涓烘暣褰�
+            else
+            {
+                classs.add(new Object[] { Integer.valueOf(str), Integer.class });
+            }
+        }
+        return classs;
+    }
+
+    /**
+     * 鑾峰彇鍙傛暟绫诲瀷
+     * 
+     * @param methodParams 鍙傛暟鐩稿叧鍒楄〃
+     * @return 鍙傛暟绫诲瀷鍒楄〃
+     */
+    public static Class<?>[] getMethodParamsType(List<Object[]> methodParams)
+    {
+        Class<?>[] classs = new Class<?>[methodParams.size()];
+        int index = 0;
+        for (Object[] os : methodParams)
+        {
+            classs[index] = (Class<?>) os[1];
+            index++;
+        }
+        return classs;
+    }
+
+    /**
+     * 鑾峰彇鍙傛暟鍊�
+     * 
+     * @param methodParams 鍙傛暟鐩稿叧鍒楄〃
+     * @return 鍙傛暟鍊煎垪琛�
+     */
+    public static Object[] getMethodParamsValue(List<Object[]> methodParams)
+    {
+        Object[] classs = new Object[methodParams.size()];
+        int index = 0;
+        for (Object[] os : methodParams)
+        {
+            classs[index] = (Object) os[0];
+            index++;
+        }
+        return classs;
+    }
+}
diff --git a/jcdm-quartz/src/main/java/com/jcdm/quartz/util/QuartzDisallowConcurrentExecution.java b/jcdm-quartz/src/main/java/com/jcdm/quartz/util/QuartzDisallowConcurrentExecution.java
new file mode 100644
index 0000000..90e10b8
--- /dev/null
+++ b/jcdm-quartz/src/main/java/com/jcdm/quartz/util/QuartzDisallowConcurrentExecution.java
@@ -0,0 +1,21 @@
+package com.jcdm.quartz.util;
+
+import org.quartz.DisallowConcurrentExecution;
+import org.quartz.JobExecutionContext;
+import com.jcdm.quartz.domain.SysJob;
+
+/**
+ * 瀹氭椂浠诲姟澶勭悊锛堢姝㈠苟鍙戞墽琛岋級
+ * 
+ * @author jc
+ *
+ */
+@DisallowConcurrentExecution
+public class QuartzDisallowConcurrentExecution extends AbstractQuartzJob
+{
+    @Override
+    protected void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception
+    {
+        JobInvokeUtil.invokeMethod(sysJob);
+    }
+}
diff --git a/jcdm-quartz/src/main/java/com/jcdm/quartz/util/QuartzJobExecution.java b/jcdm-quartz/src/main/java/com/jcdm/quartz/util/QuartzJobExecution.java
new file mode 100644
index 0000000..949cc79
--- /dev/null
+++ b/jcdm-quartz/src/main/java/com/jcdm/quartz/util/QuartzJobExecution.java
@@ -0,0 +1,19 @@
+package com.jcdm.quartz.util;
+
+import org.quartz.JobExecutionContext;
+import com.jcdm.quartz.domain.SysJob;
+
+/**
+ * 瀹氭椂浠诲姟澶勭悊锛堝厑璁稿苟鍙戞墽琛岋級
+ * 
+ * @author jc
+ *
+ */
+public class QuartzJobExecution extends AbstractQuartzJob
+{
+    @Override
+    protected void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception
+    {
+        JobInvokeUtil.invokeMethod(sysJob);
+    }
+}
diff --git a/jcdm-quartz/src/main/java/com/jcdm/quartz/util/ScheduleUtils.java b/jcdm-quartz/src/main/java/com/jcdm/quartz/util/ScheduleUtils.java
new file mode 100644
index 0000000..bf01c1d
--- /dev/null
+++ b/jcdm-quartz/src/main/java/com/jcdm/quartz/util/ScheduleUtils.java
@@ -0,0 +1,141 @@
+package com.jcdm.quartz.util;
+
+import org.quartz.CronScheduleBuilder;
+import org.quartz.CronTrigger;
+import org.quartz.Job;
+import org.quartz.JobBuilder;
+import org.quartz.JobDetail;
+import org.quartz.JobKey;
+import org.quartz.Scheduler;
+import org.quartz.SchedulerException;
+import org.quartz.TriggerBuilder;
+import org.quartz.TriggerKey;
+import com.jcdm.common.constant.Constants;
+import com.jcdm.common.constant.ScheduleConstants;
+import com.jcdm.common.exception.job.TaskException;
+import com.jcdm.common.exception.job.TaskException.Code;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.common.utils.spring.SpringUtils;
+import com.jcdm.quartz.domain.SysJob;
+
+/**
+ * 瀹氭椂浠诲姟宸ュ叿绫�
+ * 
+ * @author jc
+ *
+ */
+public class ScheduleUtils
+{
+    /**
+     * 寰楀埌quartz浠诲姟绫�
+     *
+     * @param sysJob 鎵ц璁″垝
+     * @return 鍏蜂綋鎵ц浠诲姟绫�
+     */
+    private static Class<? extends Job> getQuartzJobClass(SysJob sysJob)
+    {
+        boolean isConcurrent = "0".equals(sysJob.getConcurrent());
+        return isConcurrent ? QuartzJobExecution.class : QuartzDisallowConcurrentExecution.class;
+    }
+
+    /**
+     * 鏋勫缓浠诲姟瑙﹀彂瀵硅薄
+     */
+    public static TriggerKey getTriggerKey(Long jobId, String jobGroup)
+    {
+        return TriggerKey.triggerKey(ScheduleConstants.TASK_CLASS_NAME + jobId, jobGroup);
+    }
+
+    /**
+     * 鏋勫缓浠诲姟閿璞�
+     */
+    public static JobKey getJobKey(Long jobId, String jobGroup)
+    {
+        return JobKey.jobKey(ScheduleConstants.TASK_CLASS_NAME + jobId, jobGroup);
+    }
+
+    /**
+     * 鍒涘缓瀹氭椂浠诲姟
+     */
+    public static void createScheduleJob(Scheduler scheduler, SysJob job) throws SchedulerException, TaskException
+    {
+        Class<? extends Job> jobClass = getQuartzJobClass(job);
+        // 鏋勫缓job淇℃伅
+        Long jobId = job.getJobId();
+        String jobGroup = job.getJobGroup();
+        JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(getJobKey(jobId, jobGroup)).build();
+
+        // 琛ㄨ揪寮忚皟搴︽瀯寤哄櫒
+        CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
+        cronScheduleBuilder = handleCronScheduleMisfirePolicy(job, cronScheduleBuilder);
+
+        // 鎸夋柊鐨刢ronExpression琛ㄨ揪寮忔瀯寤轰竴涓柊鐨則rigger
+        CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(jobId, jobGroup))
+                .withSchedule(cronScheduleBuilder).build();
+
+        // 鏀惧叆鍙傛暟锛岃繍琛屾椂鐨勬柟娉曞彲浠ヨ幏鍙�
+        jobDetail.getJobDataMap().put(ScheduleConstants.TASK_PROPERTIES, job);
+
+        // 鍒ゆ柇鏄惁瀛樺湪
+        if (scheduler.checkExists(getJobKey(jobId, jobGroup)))
+        {
+            // 闃叉鍒涘缓鏃跺瓨鍦ㄦ暟鎹棶棰� 鍏堢Щ闄わ紝鐒跺悗鍦ㄦ墽琛屽垱寤烘搷浣�
+            scheduler.deleteJob(getJobKey(jobId, jobGroup));
+        }
+
+        // 鍒ゆ柇浠诲姟鏄惁杩囨湡
+        if (StringUtils.isNotNull(CronUtils.getNextExecution(job.getCronExpression())))
+        {
+            // 鎵ц璋冨害浠诲姟
+            scheduler.scheduleJob(jobDetail, trigger);
+        }
+
+        // 鏆傚仠浠诲姟
+        if (job.getStatus().equals(ScheduleConstants.Status.PAUSE.getValue()))
+        {
+            scheduler.pauseJob(ScheduleUtils.getJobKey(jobId, jobGroup));
+        }
+    }
+
+    /**
+     * 璁剧疆瀹氭椂浠诲姟绛栫暐
+     */
+    public static CronScheduleBuilder handleCronScheduleMisfirePolicy(SysJob job, CronScheduleBuilder cb)
+            throws TaskException
+    {
+        switch (job.getMisfirePolicy())
+        {
+            case ScheduleConstants.MISFIRE_DEFAULT:
+                return cb;
+            case ScheduleConstants.MISFIRE_IGNORE_MISFIRES:
+                return cb.withMisfireHandlingInstructionIgnoreMisfires();
+            case ScheduleConstants.MISFIRE_FIRE_AND_PROCEED:
+                return cb.withMisfireHandlingInstructionFireAndProceed();
+            case ScheduleConstants.MISFIRE_DO_NOTHING:
+                return cb.withMisfireHandlingInstructionDoNothing();
+            default:
+                throw new TaskException("The task misfire policy '" + job.getMisfirePolicy()
+                        + "' cannot be used in cron schedule tasks", Code.CONFIG_ERROR);
+        }
+    }
+
+    /**
+     * 妫�鏌ュ寘鍚嶆槸鍚︿负鐧藉悕鍗曢厤缃�
+     * 
+     * @param invokeTarget 鐩爣瀛楃涓�
+     * @return 缁撴灉
+     */
+    public static boolean whiteList(String invokeTarget)
+    {
+        String packageName = StringUtils.substringBefore(invokeTarget, "(");
+        int count = StringUtils.countMatches(packageName, ".");
+        if (count > 1)
+        {
+            return StringUtils.containsAnyIgnoreCase(invokeTarget, Constants.JOB_WHITELIST_STR);
+        }
+        Object obj = SpringUtils.getBean(StringUtils.split(invokeTarget, ".")[0]);
+        String beanPackageName = obj.getClass().getPackage().getName();
+        return StringUtils.containsAnyIgnoreCase(beanPackageName, Constants.JOB_WHITELIST_STR)
+                && !StringUtils.containsAnyIgnoreCase(beanPackageName, Constants.JOB_ERROR_STR);
+    }
+}
diff --git a/jcdm-quartz/src/main/resources/mapper/quartz/SysJobLogMapper.xml b/jcdm-quartz/src/main/resources/mapper/quartz/SysJobLogMapper.xml
new file mode 100644
index 0000000..332c743
--- /dev/null
+++ b/jcdm-quartz/src/main/resources/mapper/quartz/SysJobLogMapper.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.quartz.mapper.SysJobLogMapper">
+
+	<resultMap type="SysJobLog" id="SysJobLogResult">
+		<id     property="jobLogId"       column="job_log_id"      />
+		<result property="jobName"        column="job_name"        />
+		<result property="jobGroup"       column="job_group"       />
+		<result property="invokeTarget"   column="invoke_target"   />
+		<result property="jobMessage"     column="job_message"     />
+		<result property="status"         column="status"          />
+		<result property="exceptionInfo"  column="exception_info"  />
+		<result property="createTime"     column="create_time"     />
+	</resultMap>
+	
+	<sql id="selectJobLogVo">
+        select job_log_id, job_name, job_group, invoke_target, job_message, status, exception_info, create_time 
+		from sys_job_log
+    </sql>
+	
+	<select id="selectJobLogList" parameterType="SysJobLog" resultMap="SysJobLogResult">
+		<include refid="selectJobLogVo"/>
+		<where>
+			<if test="jobName != null and jobName != ''">
+				AND job_name like concat('%', #{jobName}, '%')
+			</if>
+			<if test="jobGroup != null and jobGroup != ''">
+				AND job_group = #{jobGroup}
+			</if>
+			<if test="status != null and status != ''">
+				AND status = #{status}
+			</if>
+			<if test="invokeTarget != null and invokeTarget != ''">
+				AND invoke_target like concat('%', #{invokeTarget}, '%')
+			</if>
+			<if test="params.beginTime != null and params.beginTime != ''"><!-- 寮�濮嬫椂闂存绱� -->
+				and date_format(create_time,'%y%m%d') &gt;= date_format(#{params.beginTime},'%y%m%d')
+			</if>
+			<if test="params.endTime != null and params.endTime != ''"><!-- 缁撴潫鏃堕棿妫�绱� -->
+				and date_format(create_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
+			</if>
+		</where>
+	</select>
+	
+	<select id="selectJobLogAll" resultMap="SysJobLogResult">
+		<include refid="selectJobLogVo"/>
+	</select>
+	
+	<select id="selectJobLogById" parameterType="Long" resultMap="SysJobLogResult">
+		<include refid="selectJobLogVo"/>
+		where job_log_id = #{jobLogId}
+	</select>
+	
+	<delete id="deleteJobLogById" parameterType="Long">
+ 		delete from sys_job_log where job_log_id = #{jobLogId}
+ 	</delete>
+ 	
+ 	<delete id="deleteJobLogByIds" parameterType="Long">
+ 		delete from sys_job_log where job_log_id in
+ 		<foreach collection="array" item="jobLogId" open="(" separator="," close=")">
+ 			#{jobLogId}
+        </foreach> 
+ 	</delete>
+ 	
+ 	<update id="cleanJobLog">
+        truncate table sys_job_log
+    </update>
+ 	
+ 	<insert id="insertJobLog" parameterType="SysJobLog">
+ 		insert into sys_job_log(
+ 			<if test="jobLogId != null and jobLogId != 0">job_log_id,</if>
+ 			<if test="jobName != null and jobName != ''">job_name,</if>
+ 			<if test="jobGroup != null and jobGroup != ''">job_group,</if>
+ 			<if test="invokeTarget != null and invokeTarget != ''">invoke_target,</if>
+ 			<if test="jobMessage != null and jobMessage != ''">job_message,</if>
+ 			<if test="status != null and status != ''">status,</if>
+ 			<if test="exceptionInfo != null and exceptionInfo != ''">exception_info,</if>
+ 			create_time
+ 		)values(
+ 			<if test="jobLogId != null and jobLogId != 0">#{jobLogId},</if>
+ 			<if test="jobName != null and jobName != ''">#{jobName},</if>
+ 			<if test="jobGroup != null and jobGroup != ''">#{jobGroup},</if>
+ 			<if test="invokeTarget != null and invokeTarget != ''">#{invokeTarget},</if>
+ 			<if test="jobMessage != null and jobMessage != ''">#{jobMessage},</if>
+ 			<if test="status != null and status != ''">#{status},</if>
+ 			<if test="exceptionInfo != null and exceptionInfo != ''">#{exceptionInfo},</if>
+ 			getdate()
+ 		)
+	</insert>
+
+</mapper> 
\ No newline at end of file
diff --git a/jcdm-quartz/src/main/resources/mapper/quartz/SysJobMapper.xml b/jcdm-quartz/src/main/resources/mapper/quartz/SysJobMapper.xml
new file mode 100644
index 0000000..a067636
--- /dev/null
+++ b/jcdm-quartz/src/main/resources/mapper/quartz/SysJobMapper.xml
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.quartz.mapper.SysJobMapper">
+
+	<resultMap type="SysJob" id="SysJobResult">
+		<id     property="jobId"          column="job_id"          />
+		<result property="jobName"        column="job_name"        />
+		<result property="jobGroup"       column="job_group"       />
+		<result property="invokeTarget"   column="invoke_target"   />
+		<result property="cronExpression" column="cron_expression" />
+		<result property="misfirePolicy"  column="misfire_policy"  />
+		<result property="concurrent"     column="concurrent"      />
+		<result property="status"         column="status"          />
+		<result property="createBy"       column="create_by"       />
+		<result property="createTime"     column="create_time"     />
+		<result property="updateBy"       column="update_by"       />
+		<result property="updateTime"     column="update_time"     />
+		<result property="remark"         column="remark"          />
+	</resultMap>
+	
+	<sql id="selectJobVo">
+        select job_id, job_name, job_group, invoke_target, cron_expression, misfire_policy, concurrent, status, create_by, create_time, remark 
+		from sys_job
+    </sql>
+	
+	<select id="selectJobList" parameterType="SysJob" resultMap="SysJobResult">
+		<include refid="selectJobVo"/>
+		<where>
+			<if test="jobName != null and jobName != ''">
+				AND job_name like concat('%', #{jobName}, '%')
+			</if>
+			<if test="jobGroup != null and jobGroup != ''">
+				AND job_group = #{jobGroup}
+			</if>
+			<if test="status != null and status != ''">
+				AND status = #{status}
+			</if>
+			<if test="invokeTarget != null and invokeTarget != ''">
+				AND invoke_target like concat('%', #{invokeTarget}, '%')
+			</if>
+		</where>
+	</select>
+	
+	<select id="selectJobAll" resultMap="SysJobResult">
+		<include refid="selectJobVo"/>
+	</select>
+	
+	<select id="selectJobById" parameterType="Long" resultMap="SysJobResult">
+		<include refid="selectJobVo"/>
+		where job_id = #{jobId}
+	</select>
+	
+	<delete id="deleteJobById" parameterType="Long">
+ 		delete from sys_job where job_id = #{jobId}
+ 	</delete>
+ 	
+ 	<delete id="deleteJobByIds" parameterType="Long">
+ 		delete from sys_job where job_id in
+ 		<foreach collection="array" item="jobId" open="(" separator="," close=")">
+ 			#{jobId}
+        </foreach> 
+ 	</delete>
+ 	
+ 	<update id="updateJob" parameterType="SysJob">
+ 		update sys_job
+ 		<set>
+ 			<if test="jobName != null and jobName != ''">job_name = #{jobName},</if>
+ 			<if test="jobGroup != null and jobGroup != ''">job_group = #{jobGroup},</if>
+ 			<if test="invokeTarget != null and invokeTarget != ''">invoke_target = #{invokeTarget},</if>
+ 			<if test="cronExpression != null and cronExpression != ''">cron_expression = #{cronExpression},</if>
+ 			<if test="misfirePolicy != null and misfirePolicy != ''">misfire_policy = #{misfirePolicy},</if>
+ 			<if test="concurrent != null and concurrent != ''">concurrent = #{concurrent},</if>
+ 			<if test="status !=null">status = #{status},</if>
+ 			<if test="remark != null and remark != ''">remark = #{remark},</if>
+ 			<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
+ 			update_time = getdate()
+ 		</set>
+ 		where job_id = #{jobId}
+	</update>
+ 	
+ 	<insert id="insertJob" parameterType="SysJob" useGeneratedKeys="true" keyProperty="jobId">
+ 		insert into sys_job(
+ 			<if test="jobId != null and jobId != 0">job_id,</if>
+ 			<if test="jobName != null and jobName != ''">job_name,</if>
+ 			<if test="jobGroup != null and jobGroup != ''">job_group,</if>
+ 			<if test="invokeTarget != null and invokeTarget != ''">invoke_target,</if>
+ 			<if test="cronExpression != null and cronExpression != ''">cron_expression,</if>
+ 			<if test="misfirePolicy != null and misfirePolicy != ''">misfire_policy,</if>
+ 			<if test="concurrent != null and concurrent != ''">concurrent,</if>
+ 			<if test="status != null and status != ''">status,</if>
+ 			<if test="remark != null and remark != ''">remark,</if>
+ 			<if test="createBy != null and createBy != ''">create_by,</if>
+ 			create_time
+ 		)values(
+ 			<if test="jobId != null and jobId != 0">#{jobId},</if>
+ 			<if test="jobName != null and jobName != ''">#{jobName},</if>
+ 			<if test="jobGroup != null and jobGroup != ''">#{jobGroup},</if>
+ 			<if test="invokeTarget != null and invokeTarget != ''">#{invokeTarget},</if>
+ 			<if test="cronExpression != null and cronExpression != ''">#{cronExpression},</if>
+ 			<if test="misfirePolicy != null and misfirePolicy != ''">#{misfirePolicy},</if>
+ 			<if test="concurrent != null and concurrent != ''">#{concurrent},</if>
+ 			<if test="status != null and status != ''">#{status},</if>
+ 			<if test="remark != null and remark != ''">#{remark},</if>
+ 			<if test="createBy != null and createBy != ''">#{createBy},</if>
+			getdate()
+ 		)
+	</insert>
+
+</mapper> 
\ No newline at end of file
diff --git a/jcdm-system/pom.xml b/jcdm-system/pom.xml
new file mode 100644
index 0000000..2b90455
--- /dev/null
+++ b/jcdm-system/pom.xml
@@ -0,0 +1,28 @@
+<?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">
+    <parent>
+        <artifactId>jcdm</artifactId>
+        <groupId>com.jcdm</groupId>
+        <version>3.8.6</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>jcdm-system</artifactId>
+
+    <description>
+        system绯荤粺妯″潡
+    </description>
+
+    <dependencies>
+
+        <!-- 閫氱敤宸ュ叿-->
+        <dependency>
+            <groupId>com.jcdm</groupId>
+            <artifactId>jcdm-common</artifactId>
+        </dependency>
+
+    </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/jcdm-system/src/main/java/com/jcdm/system/domain/SysCache.java b/jcdm-system/src/main/java/com/jcdm/system/domain/SysCache.java
new file mode 100644
index 0000000..811bbc0
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/domain/SysCache.java
@@ -0,0 +1,81 @@
+package com.jcdm.system.domain;
+
+import com.jcdm.common.utils.StringUtils;
+
+/**
+ * 缂撳瓨淇℃伅
+ * 
+ * @author jc
+ */
+public class SysCache
+{
+    /** 缂撳瓨鍚嶇О */
+    private String cacheName = "";
+
+    /** 缂撳瓨閿悕 */
+    private String cacheKey = "";
+
+    /** 缂撳瓨鍐呭 */
+    private String cacheValue = "";
+
+    /** 澶囨敞 */
+    private String remark = "";
+
+    public SysCache()
+    {
+
+    }
+
+    public SysCache(String cacheName, String remark)
+    {
+        this.cacheName = cacheName;
+        this.remark = remark;
+    }
+
+    public SysCache(String cacheName, String cacheKey, String cacheValue)
+    {
+        this.cacheName = StringUtils.replace(cacheName, ":", "");
+        this.cacheKey = StringUtils.replace(cacheKey, cacheName, "");
+        this.cacheValue = cacheValue;
+    }
+
+    public String getCacheName()
+    {
+        return cacheName;
+    }
+
+    public void setCacheName(String cacheName)
+    {
+        this.cacheName = cacheName;
+    }
+
+    public String getCacheKey()
+    {
+        return cacheKey;
+    }
+
+    public void setCacheKey(String cacheKey)
+    {
+        this.cacheKey = cacheKey;
+    }
+
+    public String getCacheValue()
+    {
+        return cacheValue;
+    }
+
+    public void setCacheValue(String cacheValue)
+    {
+        this.cacheValue = cacheValue;
+    }
+
+    public String getRemark()
+    {
+        return remark;
+    }
+
+    public void setRemark(String remark)
+    {
+        this.remark = remark;
+    }
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/domain/SysConfig.java b/jcdm-system/src/main/java/com/jcdm/system/domain/SysConfig.java
new file mode 100644
index 0000000..04e90fc
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/domain/SysConfig.java
@@ -0,0 +1,111 @@
+package com.jcdm.system.domain;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Size;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.annotation.Excel.ColumnType;
+import com.jcdm.common.core.domain.BaseEntity;
+
+/**
+ * 鍙傛暟閰嶇疆琛� sys_config
+ * 
+ * @author jc
+ */
+public class SysConfig extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 鍙傛暟涓婚敭 */
+    @Excel(name = "鍙傛暟涓婚敭", cellType = ColumnType.NUMERIC)
+    private Long configId;
+
+    /** 鍙傛暟鍚嶇О */
+    @Excel(name = "鍙傛暟鍚嶇О")
+    private String configName;
+
+    /** 鍙傛暟閿悕 */
+    @Excel(name = "鍙傛暟閿悕")
+    private String configKey;
+
+    /** 鍙傛暟閿�� */
+    @Excel(name = "鍙傛暟閿��")
+    private String configValue;
+
+    /** 绯荤粺鍐呯疆锛圷鏄� N鍚︼級 */
+    @Excel(name = "绯荤粺鍐呯疆", readConverterExp = "Y=鏄�,N=鍚�")
+    private String configType;
+
+    public Long getConfigId()
+    {
+        return configId;
+    }
+
+    public void setConfigId(Long configId)
+    {
+        this.configId = configId;
+    }
+
+    @NotBlank(message = "鍙傛暟鍚嶇О涓嶈兘涓虹┖")
+    @Size(min = 0, max = 100, message = "鍙傛暟鍚嶇О涓嶈兘瓒呰繃100涓瓧绗�")
+    public String getConfigName()
+    {
+        return configName;
+    }
+
+    public void setConfigName(String configName)
+    {
+        this.configName = configName;
+    }
+
+    @NotBlank(message = "鍙傛暟閿悕闀垮害涓嶈兘涓虹┖")
+    @Size(min = 0, max = 100, message = "鍙傛暟閿悕闀垮害涓嶈兘瓒呰繃100涓瓧绗�")
+    public String getConfigKey()
+    {
+        return configKey;
+    }
+
+    public void setConfigKey(String configKey)
+    {
+        this.configKey = configKey;
+    }
+
+    @NotBlank(message = "鍙傛暟閿�间笉鑳戒负绌�")
+    @Size(min = 0, max = 500, message = "鍙傛暟閿�奸暱搴︿笉鑳借秴杩�500涓瓧绗�")
+    public String getConfigValue()
+    {
+        return configValue;
+    }
+
+    public void setConfigValue(String configValue)
+    {
+        this.configValue = configValue;
+    }
+
+    public String getConfigType()
+    {
+        return configType;
+    }
+
+    public void setConfigType(String configType)
+    {
+        this.configType = configType;
+    }
+    
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("configId", getConfigId())
+            .append("configName", getConfigName())
+            .append("configKey", getConfigKey())
+            .append("configValue", getConfigValue())
+            .append("configType", getConfigType())
+            .append("createBy", getCreateBy())
+            .append("createTime", getCreateTime())
+            .append("updateBy", getUpdateBy())
+            .append("updateTime", getUpdateTime())
+            .append("remark", getRemark())
+            .toString();
+    }
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/domain/SysLogininfor.java b/jcdm-system/src/main/java/com/jcdm/system/domain/SysLogininfor.java
new file mode 100644
index 0000000..0a2d737
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/domain/SysLogininfor.java
@@ -0,0 +1,144 @@
+package com.jcdm.system.domain;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.annotation.Excel.ColumnType;
+import com.jcdm.common.core.domain.BaseEntity;
+
+/**
+ * 绯荤粺璁块棶璁板綍琛� sys_logininfor
+ * 
+ * @author jc
+ */
+public class SysLogininfor extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** ID */
+    @Excel(name = "搴忓彿", cellType = ColumnType.NUMERIC)
+    private Long infoId;
+
+    /** 鐢ㄦ埛璐﹀彿 */
+    @Excel(name = "鐢ㄦ埛璐﹀彿")
+    private String userName;
+
+    /** 鐧诲綍鐘舵�� 0鎴愬姛 1澶辫触 */
+    @Excel(name = "鐧诲綍鐘舵��", readConverterExp = "0=鎴愬姛,1=澶辫触")
+    private String status;
+
+    /** 鐧诲綍IP鍦板潃 */
+    @Excel(name = "鐧诲綍鍦板潃")
+    private String ipaddr;
+
+    /** 鐧诲綍鍦扮偣 */
+    @Excel(name = "鐧诲綍鍦扮偣")
+    private String loginLocation;
+
+    /** 娴忚鍣ㄧ被鍨� */
+    @Excel(name = "娴忚鍣�")
+    private String browser;
+
+    /** 鎿嶄綔绯荤粺 */
+    @Excel(name = "鎿嶄綔绯荤粺")
+    private String os;
+
+    /** 鎻愮ず娑堟伅 */
+    @Excel(name = "鎻愮ず娑堟伅")
+    private String msg;
+
+    /** 璁块棶鏃堕棿 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "璁块棶鏃堕棿", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
+    private Date loginTime;
+
+    public Long getInfoId()
+    {
+        return infoId;
+    }
+
+    public void setInfoId(Long infoId)
+    {
+        this.infoId = infoId;
+    }
+
+    public String getUserName()
+    {
+        return userName;
+    }
+
+    public void setUserName(String userName)
+    {
+        this.userName = userName;
+    }
+
+    public String getStatus()
+    {
+        return status;
+    }
+
+    public void setStatus(String status)
+    {
+        this.status = status;
+    }
+
+    public String getIpaddr()
+    {
+        return ipaddr;
+    }
+
+    public void setIpaddr(String ipaddr)
+    {
+        this.ipaddr = ipaddr;
+    }
+
+    public String getLoginLocation()
+    {
+        return loginLocation;
+    }
+
+    public void setLoginLocation(String loginLocation)
+    {
+        this.loginLocation = loginLocation;
+    }
+
+    public String getBrowser()
+    {
+        return browser;
+    }
+
+    public void setBrowser(String browser)
+    {
+        this.browser = browser;
+    }
+
+    public String getOs()
+    {
+        return os;
+    }
+
+    public void setOs(String os)
+    {
+        this.os = os;
+    }
+
+    public String getMsg()
+    {
+        return msg;
+    }
+
+    public void setMsg(String msg)
+    {
+        this.msg = msg;
+    }
+
+    public Date getLoginTime()
+    {
+        return loginTime;
+    }
+
+    public void setLoginTime(Date loginTime)
+    {
+        this.loginTime = loginTime;
+    }
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/domain/SysNotice.java b/jcdm-system/src/main/java/com/jcdm/system/domain/SysNotice.java
new file mode 100644
index 0000000..78ecb07
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/domain/SysNotice.java
@@ -0,0 +1,102 @@
+package com.jcdm.system.domain;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Size;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.jcdm.common.core.domain.BaseEntity;
+import com.jcdm.common.xss.Xss;
+
+/**
+ * 閫氱煡鍏憡琛� sys_notice
+ * 
+ * @author jc
+ */
+public class SysNotice extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 鍏憡ID */
+    private Long noticeId;
+
+    /** 鍏憡鏍囬 */
+    private String noticeTitle;
+
+    /** 鍏憡绫诲瀷锛�1閫氱煡 2鍏憡锛� */
+    private String noticeType;
+
+    /** 鍏憡鍐呭 */
+    private String noticeContent;
+
+    /** 鍏憡鐘舵�侊紙0姝e父 1鍏抽棴锛� */
+    private String status;
+
+    public Long getNoticeId()
+    {
+        return noticeId;
+    }
+
+    public void setNoticeId(Long noticeId)
+    {
+        this.noticeId = noticeId;
+    }
+
+    public void setNoticeTitle(String noticeTitle)
+    {
+        this.noticeTitle = noticeTitle;
+    }
+
+    @Xss(message = "鍏憡鏍囬涓嶈兘鍖呭惈鑴氭湰瀛楃")
+    @NotBlank(message = "鍏憡鏍囬涓嶈兘涓虹┖")
+    @Size(min = 0, max = 50, message = "鍏憡鏍囬涓嶈兘瓒呰繃50涓瓧绗�")
+    public String getNoticeTitle()
+    {
+        return noticeTitle;
+    }
+
+    public void setNoticeType(String noticeType)
+    {
+        this.noticeType = noticeType;
+    }
+
+    public String getNoticeType()
+    {
+        return noticeType;
+    }
+
+    public void setNoticeContent(String noticeContent)
+    {
+        this.noticeContent = noticeContent;
+    }
+
+    public String getNoticeContent()
+    {
+        return noticeContent;
+    }
+
+    public void setStatus(String status)
+    {
+        this.status = status;
+    }
+
+    public String getStatus()
+    {
+        return status;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("noticeId", getNoticeId())
+            .append("noticeTitle", getNoticeTitle())
+            .append("noticeType", getNoticeType())
+            .append("noticeContent", getNoticeContent())
+            .append("status", getStatus())
+            .append("createBy", getCreateBy())
+            .append("createTime", getCreateTime())
+            .append("updateBy", getUpdateBy())
+            .append("updateTime", getUpdateTime())
+            .append("remark", getRemark())
+            .toString();
+    }
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/domain/SysOperLog.java b/jcdm-system/src/main/java/com/jcdm/system/domain/SysOperLog.java
new file mode 100644
index 0000000..d7e4d3b
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/domain/SysOperLog.java
@@ -0,0 +1,269 @@
+package com.jcdm.system.domain;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.annotation.Excel.ColumnType;
+import com.jcdm.common.core.domain.BaseEntity;
+
+/**
+ * 鎿嶄綔鏃ュ織璁板綍琛� oper_log
+ * 
+ * @author jc
+ */
+public class SysOperLog extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 鏃ュ織涓婚敭 */
+    @Excel(name = "鎿嶄綔搴忓彿", cellType = ColumnType.NUMERIC)
+    private Long operId;
+
+    /** 鎿嶄綔妯″潡 */
+    @Excel(name = "鎿嶄綔妯″潡")
+    private String title;
+
+    /** 涓氬姟绫诲瀷锛�0鍏跺畠 1鏂板 2淇敼 3鍒犻櫎锛� */
+    @Excel(name = "涓氬姟绫诲瀷", readConverterExp = "0=鍏跺畠,1=鏂板,2=淇敼,3=鍒犻櫎,4=鎺堟潈,5=瀵煎嚭,6=瀵煎叆,7=寮洪��,8=鐢熸垚浠g爜,9=娓呯┖鏁版嵁")
+    private Integer businessType;
+
+    /** 涓氬姟绫诲瀷鏁扮粍 */
+    private Integer[] businessTypes;
+
+    /** 璇锋眰鏂规硶 */
+    @Excel(name = "璇锋眰鏂规硶")
+    private String method;
+
+    /** 璇锋眰鏂瑰紡 */
+    @Excel(name = "璇锋眰鏂瑰紡")
+    private String requestMethod;
+
+    /** 鎿嶄綔绫诲埆锛�0鍏跺畠 1鍚庡彴鐢ㄦ埛 2鎵嬫満绔敤鎴凤級 */
+    @Excel(name = "鎿嶄綔绫诲埆", readConverterExp = "0=鍏跺畠,1=鍚庡彴鐢ㄦ埛,2=鎵嬫満绔敤鎴�")
+    private Integer operatorType;
+
+    /** 鎿嶄綔浜哄憳 */
+    @Excel(name = "鎿嶄綔浜哄憳")
+    private String operName;
+
+    /** 閮ㄩ棬鍚嶇О */
+    @Excel(name = "閮ㄩ棬鍚嶇О")
+    private String deptName;
+
+    /** 璇锋眰url */
+    @Excel(name = "璇锋眰鍦板潃")
+    private String operUrl;
+
+    /** 鎿嶄綔鍦板潃 */
+    @Excel(name = "鎿嶄綔鍦板潃")
+    private String operIp;
+
+    /** 鎿嶄綔鍦扮偣 */
+    @Excel(name = "鎿嶄綔鍦扮偣")
+    private String operLocation;
+
+    /** 璇锋眰鍙傛暟 */
+    @Excel(name = "璇锋眰鍙傛暟")
+    private String operParam;
+
+    /** 杩斿洖鍙傛暟 */
+    @Excel(name = "杩斿洖鍙傛暟")
+    private String jsonResult;
+
+    /** 鎿嶄綔鐘舵�侊紙0姝e父 1寮傚父锛� */
+    @Excel(name = "鐘舵��", readConverterExp = "0=姝e父,1=寮傚父")
+    private Integer status;
+
+    /** 閿欒娑堟伅 */
+    @Excel(name = "閿欒娑堟伅")
+    private String errorMsg;
+
+    /** 鎿嶄綔鏃堕棿 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "鎿嶄綔鏃堕棿", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
+    private Date operTime;
+
+    /** 娑堣�楁椂闂� */
+    @Excel(name = "娑堣�楁椂闂�", suffix = "姣")
+    private Long costTime;
+
+    public Long getOperId()
+    {
+        return operId;
+    }
+
+    public void setOperId(Long operId)
+    {
+        this.operId = operId;
+    }
+
+    public String getTitle()
+    {
+        return title;
+    }
+
+    public void setTitle(String title)
+    {
+        this.title = title;
+    }
+
+    public Integer getBusinessType()
+    {
+        return businessType;
+    }
+
+    public void setBusinessType(Integer businessType)
+    {
+        this.businessType = businessType;
+    }
+
+    public Integer[] getBusinessTypes()
+    {
+        return businessTypes;
+    }
+
+    public void setBusinessTypes(Integer[] businessTypes)
+    {
+        this.businessTypes = businessTypes;
+    }
+
+    public String getMethod()
+    {
+        return method;
+    }
+
+    public void setMethod(String method)
+    {
+        this.method = method;
+    }
+
+    public String getRequestMethod()
+    {
+        return requestMethod;
+    }
+
+    public void setRequestMethod(String requestMethod)
+    {
+        this.requestMethod = requestMethod;
+    }
+
+    public Integer getOperatorType()
+    {
+        return operatorType;
+    }
+
+    public void setOperatorType(Integer operatorType)
+    {
+        this.operatorType = operatorType;
+    }
+
+    public String getOperName()
+    {
+        return operName;
+    }
+
+    public void setOperName(String operName)
+    {
+        this.operName = operName;
+    }
+
+    public String getDeptName()
+    {
+        return deptName;
+    }
+
+    public void setDeptName(String deptName)
+    {
+        this.deptName = deptName;
+    }
+
+    public String getOperUrl()
+    {
+        return operUrl;
+    }
+
+    public void setOperUrl(String operUrl)
+    {
+        this.operUrl = operUrl;
+    }
+
+    public String getOperIp()
+    {
+        return operIp;
+    }
+
+    public void setOperIp(String operIp)
+    {
+        this.operIp = operIp;
+    }
+
+    public String getOperLocation()
+    {
+        return operLocation;
+    }
+
+    public void setOperLocation(String operLocation)
+    {
+        this.operLocation = operLocation;
+    }
+
+    public String getOperParam()
+    {
+        return operParam;
+    }
+
+    public void setOperParam(String operParam)
+    {
+        this.operParam = operParam;
+    }
+
+    public String getJsonResult()
+    {
+        return jsonResult;
+    }
+
+    public void setJsonResult(String jsonResult)
+    {
+        this.jsonResult = jsonResult;
+    }
+
+    public Integer getStatus()
+    {
+        return status;
+    }
+
+    public void setStatus(Integer status)
+    {
+        this.status = status;
+    }
+
+    public String getErrorMsg()
+    {
+        return errorMsg;
+    }
+
+    public void setErrorMsg(String errorMsg)
+    {
+        this.errorMsg = errorMsg;
+    }
+
+    public Date getOperTime()
+    {
+        return operTime;
+    }
+
+    public void setOperTime(Date operTime)
+    {
+        this.operTime = operTime;
+    }
+
+    public Long getCostTime()
+    {
+        return costTime;
+    }
+
+    public void setCostTime(Long costTime)
+    {
+        this.costTime = costTime;
+    }
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/domain/SysPost.java b/jcdm-system/src/main/java/com/jcdm/system/domain/SysPost.java
new file mode 100644
index 0000000..2bf40d7
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/domain/SysPost.java
@@ -0,0 +1,124 @@
+package com.jcdm.system.domain;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.jcdm.common.annotation.Excel;
+import com.jcdm.common.annotation.Excel.ColumnType;
+import com.jcdm.common.core.domain.BaseEntity;
+
+/**
+ * 宀椾綅琛� sys_post
+ * 
+ * @author jc
+ */
+public class SysPost extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 宀椾綅搴忓彿 */
+    @Excel(name = "宀椾綅搴忓彿", cellType = ColumnType.NUMERIC)
+    private Long postId;
+
+    /** 宀椾綅缂栫爜 */
+    @Excel(name = "宀椾綅缂栫爜")
+    private String postCode;
+
+    /** 宀椾綅鍚嶇О */
+    @Excel(name = "宀椾綅鍚嶇О")
+    private String postName;
+
+    /** 宀椾綅鎺掑簭 */
+    @Excel(name = "宀椾綅鎺掑簭")
+    private Integer postSort;
+
+    /** 鐘舵�侊紙0姝e父 1鍋滅敤锛� */
+    @Excel(name = "鐘舵��", readConverterExp = "0=姝e父,1=鍋滅敤")
+    private String status;
+
+    /** 鐢ㄦ埛鏄惁瀛樺湪姝ゅ矖浣嶆爣璇� 榛樿涓嶅瓨鍦� */
+    private boolean flag = false;
+
+    public Long getPostId()
+    {
+        return postId;
+    }
+
+    public void setPostId(Long postId)
+    {
+        this.postId = postId;
+    }
+
+    @NotBlank(message = "宀椾綅缂栫爜涓嶈兘涓虹┖")
+    @Size(min = 0, max = 64, message = "宀椾綅缂栫爜闀垮害涓嶈兘瓒呰繃64涓瓧绗�")
+    public String getPostCode()
+    {
+        return postCode;
+    }
+
+    public void setPostCode(String postCode)
+    {
+        this.postCode = postCode;
+    }
+
+    @NotBlank(message = "宀椾綅鍚嶇О涓嶈兘涓虹┖")
+    @Size(min = 0, max = 50, message = "宀椾綅鍚嶇О闀垮害涓嶈兘瓒呰繃50涓瓧绗�")
+    public String getPostName()
+    {
+        return postName;
+    }
+
+    public void setPostName(String postName)
+    {
+        this.postName = postName;
+    }
+
+    @NotNull(message = "鏄剧ず椤哄簭涓嶈兘涓虹┖")
+    public Integer getPostSort()
+    {
+        return postSort;
+    }
+
+    public void setPostSort(Integer postSort)
+    {
+        this.postSort = postSort;
+    }
+
+    public String getStatus()
+    {
+        return status;
+    }
+
+    public void setStatus(String status)
+    {
+        this.status = status;
+    }
+
+    public boolean isFlag()
+    {
+        return flag;
+    }
+
+    public void setFlag(boolean flag)
+    {
+        this.flag = flag;
+    }
+    
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("postId", getPostId())
+            .append("postCode", getPostCode())
+            .append("postName", getPostName())
+            .append("postSort", getPostSort())
+            .append("status", getStatus())
+            .append("createBy", getCreateBy())
+            .append("createTime", getCreateTime())
+            .append("updateBy", getUpdateBy())
+            .append("updateTime", getUpdateTime())
+            .append("remark", getRemark())
+            .toString();
+    }
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/domain/SysRoleDept.java b/jcdm-system/src/main/java/com/jcdm/system/domain/SysRoleDept.java
new file mode 100644
index 0000000..c72fdff
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/domain/SysRoleDept.java
@@ -0,0 +1,46 @@
+package com.jcdm.system.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 瑙掕壊鍜岄儴闂ㄥ叧鑱� sys_role_dept
+ * 
+ * @author jc
+ */
+public class SysRoleDept
+{
+    /** 瑙掕壊ID */
+    private Long roleId;
+    
+    /** 閮ㄩ棬ID */
+    private Long deptId;
+
+    public Long getRoleId()
+    {
+        return roleId;
+    }
+
+    public void setRoleId(Long roleId)
+    {
+        this.roleId = roleId;
+    }
+
+    public Long getDeptId()
+    {
+        return deptId;
+    }
+
+    public void setDeptId(Long deptId)
+    {
+        this.deptId = deptId;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("roleId", getRoleId())
+            .append("deptId", getDeptId())
+            .toString();
+    }
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/domain/SysRoleMenu.java b/jcdm-system/src/main/java/com/jcdm/system/domain/SysRoleMenu.java
new file mode 100644
index 0000000..6cc582c
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/domain/SysRoleMenu.java
@@ -0,0 +1,46 @@
+package com.jcdm.system.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 瑙掕壊鍜岃彍鍗曞叧鑱� sys_role_menu
+ * 
+ * @author jc
+ */
+public class SysRoleMenu
+{
+    /** 瑙掕壊ID */
+    private Long roleId;
+    
+    /** 鑿滃崟ID */
+    private Long menuId;
+
+    public Long getRoleId()
+    {
+        return roleId;
+    }
+
+    public void setRoleId(Long roleId)
+    {
+        this.roleId = roleId;
+    }
+
+    public Long getMenuId()
+    {
+        return menuId;
+    }
+
+    public void setMenuId(Long menuId)
+    {
+        this.menuId = menuId;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("roleId", getRoleId())
+            .append("menuId", getMenuId())
+            .toString();
+    }
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/domain/SysUserOnline.java b/jcdm-system/src/main/java/com/jcdm/system/domain/SysUserOnline.java
new file mode 100644
index 0000000..d2bd576
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/domain/SysUserOnline.java
@@ -0,0 +1,113 @@
+package com.jcdm.system.domain;
+
+/**
+ * 褰撳墠鍦ㄧ嚎浼氳瘽
+ * 
+ * @author jc
+ */
+public class SysUserOnline
+{
+    /** 浼氳瘽缂栧彿 */
+    private String tokenId;
+
+    /** 閮ㄩ棬鍚嶇О */
+    private String deptName;
+
+    /** 鐢ㄦ埛鍚嶇О */
+    private String userName;
+
+    /** 鐧诲綍IP鍦板潃 */
+    private String ipaddr;
+
+    /** 鐧诲綍鍦板潃 */
+    private String loginLocation;
+
+    /** 娴忚鍣ㄧ被鍨� */
+    private String browser;
+
+    /** 鎿嶄綔绯荤粺 */
+    private String os;
+
+    /** 鐧诲綍鏃堕棿 */
+    private Long loginTime;
+
+    public String getTokenId()
+    {
+        return tokenId;
+    }
+
+    public void setTokenId(String tokenId)
+    {
+        this.tokenId = tokenId;
+    }
+
+    public String getDeptName()
+    {
+        return deptName;
+    }
+
+    public void setDeptName(String deptName)
+    {
+        this.deptName = deptName;
+    }
+
+    public String getUserName()
+    {
+        return userName;
+    }
+
+    public void setUserName(String userName)
+    {
+        this.userName = userName;
+    }
+
+    public String getIpaddr()
+    {
+        return ipaddr;
+    }
+
+    public void setIpaddr(String ipaddr)
+    {
+        this.ipaddr = ipaddr;
+    }
+
+    public String getLoginLocation()
+    {
+        return loginLocation;
+    }
+
+    public void setLoginLocation(String loginLocation)
+    {
+        this.loginLocation = loginLocation;
+    }
+
+    public String getBrowser()
+    {
+        return browser;
+    }
+
+    public void setBrowser(String browser)
+    {
+        this.browser = browser;
+    }
+
+    public String getOs()
+    {
+        return os;
+    }
+
+    public void setOs(String os)
+    {
+        this.os = os;
+    }
+
+    public Long getLoginTime()
+    {
+        return loginTime;
+    }
+
+    public void setLoginTime(Long loginTime)
+    {
+        this.loginTime = loginTime;
+    }
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/domain/SysUserPost.java b/jcdm-system/src/main/java/com/jcdm/system/domain/SysUserPost.java
new file mode 100644
index 0000000..a422f64
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/domain/SysUserPost.java
@@ -0,0 +1,46 @@
+package com.jcdm.system.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 鐢ㄦ埛鍜屽矖浣嶅叧鑱� sys_user_post
+ * 
+ * @author jc
+ */
+public class SysUserPost
+{
+    /** 鐢ㄦ埛ID */
+    private Long userId;
+    
+    /** 宀椾綅ID */
+    private Long postId;
+
+    public Long getUserId()
+    {
+        return userId;
+    }
+
+    public void setUserId(Long userId)
+    {
+        this.userId = userId;
+    }
+
+    public Long getPostId()
+    {
+        return postId;
+    }
+
+    public void setPostId(Long postId)
+    {
+        this.postId = postId;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("userId", getUserId())
+            .append("postId", getPostId())
+            .toString();
+    }
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/domain/SysUserRole.java b/jcdm-system/src/main/java/com/jcdm/system/domain/SysUserRole.java
new file mode 100644
index 0000000..f573936
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/domain/SysUserRole.java
@@ -0,0 +1,46 @@
+package com.jcdm.system.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 鐢ㄦ埛鍜岃鑹插叧鑱� sys_user_role
+ * 
+ * @author jc
+ */
+public class SysUserRole
+{
+    /** 鐢ㄦ埛ID */
+    private Long userId;
+    
+    /** 瑙掕壊ID */
+    private Long roleId;
+
+    public Long getUserId()
+    {
+        return userId;
+    }
+
+    public void setUserId(Long userId)
+    {
+        this.userId = userId;
+    }
+
+    public Long getRoleId()
+    {
+        return roleId;
+    }
+
+    public void setRoleId(Long roleId)
+    {
+        this.roleId = roleId;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("userId", getUserId())
+            .append("roleId", getRoleId())
+            .toString();
+    }
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/domain/vo/MetaVo.java b/jcdm-system/src/main/java/com/jcdm/system/domain/vo/MetaVo.java
new file mode 100644
index 0000000..57ebfea
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/domain/vo/MetaVo.java
@@ -0,0 +1,106 @@
+package com.jcdm.system.domain.vo;
+
+import com.jcdm.common.utils.StringUtils;
+
+/**
+ * 璺敱鏄剧ず淇℃伅
+ * 
+ * @author jc
+ */
+public class MetaVo
+{
+    /**
+     * 璁剧疆璇ヨ矾鐢卞湪渚ц竟鏍忓拰闈㈠寘灞戜腑灞曠ず鐨勫悕瀛�
+     */
+    private String title;
+
+    /**
+     * 璁剧疆璇ヨ矾鐢辩殑鍥炬爣锛屽搴旇矾寰剆rc/assets/icons/svg
+     */
+    private String icon;
+
+    /**
+     * 璁剧疆涓簍rue锛屽垯涓嶄細琚� <keep-alive>缂撳瓨
+     */
+    private boolean noCache;
+
+    /**
+     * 鍐呴摼鍦板潃锛坔ttp(s)://寮�澶达級
+     */
+    private String link;
+
+    public MetaVo()
+    {
+    }
+
+    public MetaVo(String title, String icon)
+    {
+        this.title = title;
+        this.icon = icon;
+    }
+
+    public MetaVo(String title, String icon, boolean noCache)
+    {
+        this.title = title;
+        this.icon = icon;
+        this.noCache = noCache;
+    }
+
+    public MetaVo(String title, String icon, String link)
+    {
+        this.title = title;
+        this.icon = icon;
+        this.link = link;
+    }
+
+    public MetaVo(String title, String icon, boolean noCache, String link)
+    {
+        this.title = title;
+        this.icon = icon;
+        this.noCache = noCache;
+        if (StringUtils.ishttp(link))
+        {
+            this.link = link;
+        }
+    }
+
+    public boolean isNoCache()
+    {
+        return noCache;
+    }
+
+    public void setNoCache(boolean noCache)
+    {
+        this.noCache = noCache;
+    }
+
+    public String getTitle()
+    {
+        return title;
+    }
+
+    public void setTitle(String title)
+    {
+        this.title = title;
+    }
+
+    public String getIcon()
+    {
+        return icon;
+    }
+
+    public void setIcon(String icon)
+    {
+        this.icon = icon;
+    }
+
+    public String getLink()
+    {
+        return link;
+    }
+
+    public void setLink(String link)
+    {
+        this.link = link;
+    }
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/domain/vo/RouterVo.java b/jcdm-system/src/main/java/com/jcdm/system/domain/vo/RouterVo.java
new file mode 100644
index 0000000..236bc01
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/domain/vo/RouterVo.java
@@ -0,0 +1,148 @@
+package com.jcdm.system.domain.vo;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import java.util.List;
+
+/**
+ * 璺敱閰嶇疆淇℃伅
+ * 
+ * @author jc
+ */
+@JsonInclude(JsonInclude.Include.NON_EMPTY)
+public class RouterVo
+{
+    /**
+     * 璺敱鍚嶅瓧
+     */
+    private String name;
+
+    /**
+     * 璺敱鍦板潃
+     */
+    private String path;
+
+    /**
+     * 鏄惁闅愯棌璺敱锛屽綋璁剧疆 true 鐨勬椂鍊欒璺敱涓嶄細鍐嶄晶杈规爮鍑虹幇
+     */
+    private boolean hidden;
+
+    /**
+     * 閲嶅畾鍚戝湴鍧�锛屽綋璁剧疆 noRedirect 鐨勬椂鍊欒璺敱鍦ㄩ潰鍖呭睉瀵艰埅涓笉鍙鐐瑰嚮
+     */
+    private String redirect;
+
+    /**
+     * 缁勪欢鍦板潃
+     */
+    private String component;
+
+    /**
+     * 璺敱鍙傛暟锛氬 {"id": 1, "name": "ry"}
+     */
+    private String query;
+
+    /**
+     * 褰撲綘涓�涓矾鐢变笅闈㈢殑 children 澹版槑鐨勮矾鐢卞ぇ浜�1涓椂锛岃嚜鍔ㄤ細鍙樻垚宓屽鐨勬ā寮�--濡傜粍浠堕〉闈�
+     */
+    private Boolean alwaysShow;
+
+    /**
+     * 鍏朵粬鍏冪礌
+     */
+    private MetaVo meta;
+
+    /**
+     * 瀛愯矾鐢�
+     */
+    private List<RouterVo> children;
+
+    public String getName()
+    {
+        return name;
+    }
+
+    public void setName(String name)
+    {
+        this.name = name;
+    }
+
+    public String getPath()
+    {
+        return path;
+    }
+
+    public void setPath(String path)
+    {
+        this.path = path;
+    }
+
+    public boolean getHidden()
+    {
+        return hidden;
+    }
+
+    public void setHidden(boolean hidden)
+    {
+        this.hidden = hidden;
+    }
+
+    public String getRedirect()
+    {
+        return redirect;
+    }
+
+    public void setRedirect(String redirect)
+    {
+        this.redirect = redirect;
+    }
+
+    public String getComponent()
+    {
+        return component;
+    }
+
+    public void setComponent(String component)
+    {
+        this.component = component;
+    }
+
+    public String getQuery()
+    {
+        return query;
+    }
+
+    public void setQuery(String query)
+    {
+        this.query = query;
+    }
+
+    public Boolean getAlwaysShow()
+    {
+        return alwaysShow;
+    }
+
+    public void setAlwaysShow(Boolean alwaysShow)
+    {
+        this.alwaysShow = alwaysShow;
+    }
+
+    public MetaVo getMeta()
+    {
+        return meta;
+    }
+
+    public void setMeta(MetaVo meta)
+    {
+        this.meta = meta;
+    }
+
+    public List<RouterVo> getChildren()
+    {
+        return children;
+    }
+
+    public void setChildren(List<RouterVo> children)
+    {
+        this.children = children;
+    }
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/mapper/SysConfigMapper.java b/jcdm-system/src/main/java/com/jcdm/system/mapper/SysConfigMapper.java
new file mode 100644
index 0000000..a43b2e2
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/mapper/SysConfigMapper.java
@@ -0,0 +1,76 @@
+package com.jcdm.system.mapper;
+
+import java.util.List;
+import com.jcdm.system.domain.SysConfig;
+
+/**
+ * 鍙傛暟閰嶇疆 鏁版嵁灞�
+ * 
+ * @author jc
+ */
+public interface SysConfigMapper
+{
+    /**
+     * 鏌ヨ鍙傛暟閰嶇疆淇℃伅
+     * 
+     * @param config 鍙傛暟閰嶇疆淇℃伅
+     * @return 鍙傛暟閰嶇疆淇℃伅
+     */
+    public SysConfig selectConfig(SysConfig config);
+
+    /**
+     * 閫氳繃ID鏌ヨ閰嶇疆
+     * 
+     * @param configId 鍙傛暟ID
+     * @return 鍙傛暟閰嶇疆淇℃伅
+     */
+    public SysConfig selectConfigById(Long configId);
+
+    /**
+     * 鏌ヨ鍙傛暟閰嶇疆鍒楄〃
+     * 
+     * @param config 鍙傛暟閰嶇疆淇℃伅
+     * @return 鍙傛暟閰嶇疆闆嗗悎
+     */
+    public List<SysConfig> selectConfigList(SysConfig config);
+
+    /**
+     * 鏍规嵁閿悕鏌ヨ鍙傛暟閰嶇疆淇℃伅
+     * 
+     * @param configKey 鍙傛暟閿悕
+     * @return 鍙傛暟閰嶇疆淇℃伅
+     */
+    public SysConfig checkConfigKeyUnique(String configKey);
+
+    /**
+     * 鏂板鍙傛暟閰嶇疆
+     * 
+     * @param config 鍙傛暟閰嶇疆淇℃伅
+     * @return 缁撴灉
+     */
+    public int insertConfig(SysConfig config);
+
+    /**
+     * 淇敼鍙傛暟閰嶇疆
+     * 
+     * @param config 鍙傛暟閰嶇疆淇℃伅
+     * @return 缁撴灉
+     */
+    public int updateConfig(SysConfig config);
+
+    /**
+     * 鍒犻櫎鍙傛暟閰嶇疆
+     * 
+     * @param configId 鍙傛暟ID
+     * @return 缁撴灉
+     */
+    public int deleteConfigById(Long configId);
+
+    /**
+     * 鎵归噺鍒犻櫎鍙傛暟淇℃伅
+     * 
+     * @param configIds 闇�瑕佸垹闄ょ殑鍙傛暟ID
+     * @return 缁撴灉
+     */
+    public int deleteConfigByIds(Long[] configIds);
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/mapper/SysDeptMapper.java b/jcdm-system/src/main/java/com/jcdm/system/mapper/SysDeptMapper.java
new file mode 100644
index 0000000..e867f0a
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/mapper/SysDeptMapper.java
@@ -0,0 +1,118 @@
+package com.jcdm.system.mapper;
+
+import java.util.List;
+import org.apache.ibatis.annotations.Param;
+import com.jcdm.common.core.domain.entity.SysDept;
+
+/**
+ * 閮ㄩ棬绠$悊 鏁版嵁灞�
+ * 
+ * @author jc
+ */
+public interface SysDeptMapper
+{
+    /**
+     * 鏌ヨ閮ㄩ棬绠$悊鏁版嵁
+     * 
+     * @param dept 閮ㄩ棬淇℃伅
+     * @return 閮ㄩ棬淇℃伅闆嗗悎
+     */
+    public List<SysDept> selectDeptList(SysDept dept);
+
+    /**
+     * 鏍规嵁瑙掕壊ID鏌ヨ閮ㄩ棬鏍戜俊鎭�
+     * 
+     * @param roleId 瑙掕壊ID
+     * @param deptCheckStrictly 閮ㄩ棬鏍戦�夋嫨椤规槸鍚﹀叧鑱旀樉绀�
+     * @return 閫変腑閮ㄩ棬鍒楄〃
+     */
+    public List<Long> selectDeptListByRoleId(@Param("roleId") Long roleId, @Param("deptCheckStrictly") boolean deptCheckStrictly);
+
+    /**
+     * 鏍规嵁閮ㄩ棬ID鏌ヨ淇℃伅
+     * 
+     * @param deptId 閮ㄩ棬ID
+     * @return 閮ㄩ棬淇℃伅
+     */
+    public SysDept selectDeptById(Long deptId);
+
+    /**
+     * 鏍规嵁ID鏌ヨ鎵�鏈夊瓙閮ㄩ棬
+     * 
+     * @param deptId 閮ㄩ棬ID
+     * @return 閮ㄩ棬鍒楄〃
+     */
+    public List<SysDept> selectChildrenDeptById(Long deptId);
+
+    /**
+     * 鏍规嵁ID鏌ヨ鎵�鏈夊瓙閮ㄩ棬锛堟甯哥姸鎬侊級
+     * 
+     * @param deptId 閮ㄩ棬ID
+     * @return 瀛愰儴闂ㄦ暟
+     */
+    public int selectNormalChildrenDeptById(Long deptId);
+
+    /**
+     * 鏄惁瀛樺湪瀛愯妭鐐�
+     * 
+     * @param deptId 閮ㄩ棬ID
+     * @return 缁撴灉
+     */
+    public int hasChildByDeptId(Long deptId);
+
+    /**
+     * 鏌ヨ閮ㄩ棬鏄惁瀛樺湪鐢ㄦ埛
+     * 
+     * @param deptId 閮ㄩ棬ID
+     * @return 缁撴灉
+     */
+    public int checkDeptExistUser(Long deptId);
+
+    /**
+     * 鏍¢獙閮ㄩ棬鍚嶇О鏄惁鍞竴
+     * 
+     * @param deptName 閮ㄩ棬鍚嶇О
+     * @param parentId 鐖堕儴闂↖D
+     * @return 缁撴灉
+     */
+    public SysDept checkDeptNameUnique(@Param("deptName") String deptName, @Param("parentId") Long parentId);
+
+    /**
+     * 鏂板閮ㄩ棬淇℃伅
+     * 
+     * @param dept 閮ㄩ棬淇℃伅
+     * @return 缁撴灉
+     */
+    public int insertDept(SysDept dept);
+
+    /**
+     * 淇敼閮ㄩ棬淇℃伅
+     * 
+     * @param dept 閮ㄩ棬淇℃伅
+     * @return 缁撴灉
+     */
+    public int updateDept(SysDept dept);
+
+    /**
+     * 淇敼鎵�鍦ㄩ儴闂ㄦ甯哥姸鎬�
+     * 
+     * @param deptIds 閮ㄩ棬ID缁�
+     */
+    public void updateDeptStatusNormal(Long[] deptIds);
+
+    /**
+     * 淇敼瀛愬厓绱犲叧绯�
+     * 
+     * @param depts 瀛愬厓绱�
+     * @return 缁撴灉
+     */
+    public int updateDeptChildren(@Param("depts") List<SysDept> depts);
+
+    /**
+     * 鍒犻櫎閮ㄩ棬绠$悊淇℃伅
+     * 
+     * @param deptId 閮ㄩ棬ID
+     * @return 缁撴灉
+     */
+    public int deleteDeptById(Long deptId);
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/mapper/SysDictDataMapper.java b/jcdm-system/src/main/java/com/jcdm/system/mapper/SysDictDataMapper.java
new file mode 100644
index 0000000..9a372df
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/mapper/SysDictDataMapper.java
@@ -0,0 +1,95 @@
+package com.jcdm.system.mapper;
+
+import java.util.List;
+import org.apache.ibatis.annotations.Param;
+import com.jcdm.common.core.domain.entity.SysDictData;
+
+/**
+ * 瀛楀吀琛� 鏁版嵁灞�
+ * 
+ * @author jc
+ */
+public interface SysDictDataMapper
+{
+    /**
+     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瀛楀吀鏁版嵁
+     * 
+     * @param dictData 瀛楀吀鏁版嵁淇℃伅
+     * @return 瀛楀吀鏁版嵁闆嗗悎淇℃伅
+     */
+    public List<SysDictData> selectDictDataList(SysDictData dictData);
+
+    /**
+     * 鏍规嵁瀛楀吀绫诲瀷鏌ヨ瀛楀吀鏁版嵁
+     * 
+     * @param dictType 瀛楀吀绫诲瀷
+     * @return 瀛楀吀鏁版嵁闆嗗悎淇℃伅
+     */
+    public List<SysDictData> selectDictDataByType(String dictType);
+
+    /**
+     * 鏍规嵁瀛楀吀绫诲瀷鍜屽瓧鍏搁敭鍊兼煡璇㈠瓧鍏告暟鎹俊鎭�
+     * 
+     * @param dictType 瀛楀吀绫诲瀷
+     * @param dictValue 瀛楀吀閿��
+     * @return 瀛楀吀鏍囩
+     */
+    public String selectDictLabel(@Param("dictType") String dictType, @Param("dictValue") String dictValue);
+
+    /**
+     * 鏍规嵁瀛楀吀鏁版嵁ID鏌ヨ淇℃伅
+     * 
+     * @param dictCode 瀛楀吀鏁版嵁ID
+     * @return 瀛楀吀鏁版嵁
+     */
+    public SysDictData selectDictDataById(Long dictCode);
+
+    /**
+     * 鏌ヨ瀛楀吀鏁版嵁
+     * 
+     * @param dictType 瀛楀吀绫诲瀷
+     * @return 瀛楀吀鏁版嵁
+     */
+    public int countDictDataByType(String dictType);
+
+    /**
+     * 閫氳繃瀛楀吀ID鍒犻櫎瀛楀吀鏁版嵁淇℃伅
+     * 
+     * @param dictCode 瀛楀吀鏁版嵁ID
+     * @return 缁撴灉
+     */
+    public int deleteDictDataById(Long dictCode);
+
+    /**
+     * 鎵归噺鍒犻櫎瀛楀吀鏁版嵁淇℃伅
+     * 
+     * @param dictCodes 闇�瑕佸垹闄ょ殑瀛楀吀鏁版嵁ID
+     * @return 缁撴灉
+     */
+    public int deleteDictDataByIds(Long[] dictCodes);
+
+    /**
+     * 鏂板瀛楀吀鏁版嵁淇℃伅
+     * 
+     * @param dictData 瀛楀吀鏁版嵁淇℃伅
+     * @return 缁撴灉
+     */
+    public int insertDictData(SysDictData dictData);
+
+    /**
+     * 淇敼瀛楀吀鏁版嵁淇℃伅
+     * 
+     * @param dictData 瀛楀吀鏁版嵁淇℃伅
+     * @return 缁撴灉
+     */
+    public int updateDictData(SysDictData dictData);
+
+    /**
+     * 鍚屾淇敼瀛楀吀绫诲瀷
+     * 
+     * @param oldDictType 鏃у瓧鍏哥被鍨�
+     * @param newDictType 鏂版棫瀛楀吀绫诲瀷
+     * @return 缁撴灉
+     */
+    public int updateDictDataType(@Param("oldDictType") String oldDictType, @Param("newDictType") String newDictType);
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/mapper/SysDictTypeMapper.java b/jcdm-system/src/main/java/com/jcdm/system/mapper/SysDictTypeMapper.java
new file mode 100644
index 0000000..e34db08
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/mapper/SysDictTypeMapper.java
@@ -0,0 +1,83 @@
+package com.jcdm.system.mapper;
+
+import java.util.List;
+import com.jcdm.common.core.domain.entity.SysDictType;
+
+/**
+ * 瀛楀吀琛� 鏁版嵁灞�
+ * 
+ * @author jc
+ */
+public interface SysDictTypeMapper
+{
+    /**
+     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瀛楀吀绫诲瀷
+     * 
+     * @param dictType 瀛楀吀绫诲瀷淇℃伅
+     * @return 瀛楀吀绫诲瀷闆嗗悎淇℃伅
+     */
+    public List<SysDictType> selectDictTypeList(SysDictType dictType);
+
+    /**
+     * 鏍规嵁鎵�鏈夊瓧鍏哥被鍨�
+     * 
+     * @return 瀛楀吀绫诲瀷闆嗗悎淇℃伅
+     */
+    public List<SysDictType> selectDictTypeAll();
+
+    /**
+     * 鏍规嵁瀛楀吀绫诲瀷ID鏌ヨ淇℃伅
+     * 
+     * @param dictId 瀛楀吀绫诲瀷ID
+     * @return 瀛楀吀绫诲瀷
+     */
+    public SysDictType selectDictTypeById(Long dictId);
+
+    /**
+     * 鏍规嵁瀛楀吀绫诲瀷鏌ヨ淇℃伅
+     * 
+     * @param dictType 瀛楀吀绫诲瀷
+     * @return 瀛楀吀绫诲瀷
+     */
+    public SysDictType selectDictTypeByType(String dictType);
+
+    /**
+     * 閫氳繃瀛楀吀ID鍒犻櫎瀛楀吀淇℃伅
+     * 
+     * @param dictId 瀛楀吀ID
+     * @return 缁撴灉
+     */
+    public int deleteDictTypeById(Long dictId);
+
+    /**
+     * 鎵归噺鍒犻櫎瀛楀吀绫诲瀷淇℃伅
+     * 
+     * @param dictIds 闇�瑕佸垹闄ょ殑瀛楀吀ID
+     * @return 缁撴灉
+     */
+    public int deleteDictTypeByIds(Long[] dictIds);
+
+    /**
+     * 鏂板瀛楀吀绫诲瀷淇℃伅
+     * 
+     * @param dictType 瀛楀吀绫诲瀷淇℃伅
+     * @return 缁撴灉
+     */
+    public int insertDictType(SysDictType dictType);
+
+    /**
+     * 淇敼瀛楀吀绫诲瀷淇℃伅
+     * 
+     * @param dictType 瀛楀吀绫诲瀷淇℃伅
+     * @return 缁撴灉
+     */
+    public int updateDictType(SysDictType dictType);
+
+    /**
+     * 鏍¢獙瀛楀吀绫诲瀷绉版槸鍚﹀敮涓�
+     * 
+     * @param dictType 瀛楀吀绫诲瀷
+     * @return 缁撴灉
+     */
+    public SysDictType checkDictTypeUnique(String dictType);
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/mapper/SysLogininforMapper.java b/jcdm-system/src/main/java/com/jcdm/system/mapper/SysLogininforMapper.java
new file mode 100644
index 0000000..631f10e
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/mapper/SysLogininforMapper.java
@@ -0,0 +1,42 @@
+package com.jcdm.system.mapper;
+
+import java.util.List;
+import com.jcdm.system.domain.SysLogininfor;
+
+/**
+ * 绯荤粺璁块棶鏃ュ織鎯呭喌淇℃伅 鏁版嵁灞�
+ * 
+ * @author jc
+ */
+public interface SysLogininforMapper
+{
+    /**
+     * 鏂板绯荤粺鐧诲綍鏃ュ織
+     * 
+     * @param logininfor 璁块棶鏃ュ織瀵硅薄
+     */
+    public void insertLogininfor(SysLogininfor logininfor);
+
+    /**
+     * 鏌ヨ绯荤粺鐧诲綍鏃ュ織闆嗗悎
+     * 
+     * @param logininfor 璁块棶鏃ュ織瀵硅薄
+     * @return 鐧诲綍璁板綍闆嗗悎
+     */
+    public List<SysLogininfor> selectLogininforList(SysLogininfor logininfor);
+
+    /**
+     * 鎵归噺鍒犻櫎绯荤粺鐧诲綍鏃ュ織
+     * 
+     * @param infoIds 闇�瑕佸垹闄ょ殑鐧诲綍鏃ュ織ID
+     * @return 缁撴灉
+     */
+    public int deleteLogininforByIds(Long[] infoIds);
+
+    /**
+     * 娓呯┖绯荤粺鐧诲綍鏃ュ織
+     * 
+     * @return 缁撴灉
+     */
+    public int cleanLogininfor();
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/mapper/SysMenuMapper.java b/jcdm-system/src/main/java/com/jcdm/system/mapper/SysMenuMapper.java
new file mode 100644
index 0000000..f36bd7c
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/mapper/SysMenuMapper.java
@@ -0,0 +1,125 @@
+package com.jcdm.system.mapper;
+
+import java.util.List;
+import org.apache.ibatis.annotations.Param;
+import com.jcdm.common.core.domain.entity.SysMenu;
+
+/**
+ * 鑿滃崟琛� 鏁版嵁灞�
+ *
+ * @author jc
+ */
+public interface SysMenuMapper
+{
+    /**
+     * 鏌ヨ绯荤粺鑿滃崟鍒楄〃
+     *
+     * @param menu 鑿滃崟淇℃伅
+     * @return 鑿滃崟鍒楄〃
+     */
+    public List<SysMenu> selectMenuList(SysMenu menu);
+
+    /**
+     * 鏍规嵁鐢ㄦ埛鎵�鏈夋潈闄�
+     *
+     * @return 鏉冮檺鍒楄〃
+     */
+    public List<String> selectMenuPerms();
+
+    /**
+     * 鏍规嵁鐢ㄦ埛鏌ヨ绯荤粺鑿滃崟鍒楄〃
+     *
+     * @param menu 鑿滃崟淇℃伅
+     * @return 鑿滃崟鍒楄〃
+     */
+    public List<SysMenu> selectMenuListByUserId(SysMenu menu);
+
+    /**
+     * 鏍规嵁瑙掕壊ID鏌ヨ鏉冮檺
+     * 
+     * @param roleId 瑙掕壊ID
+     * @return 鏉冮檺鍒楄〃
+     */
+    public List<String> selectMenuPermsByRoleId(Long roleId);
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鏌ヨ鏉冮檺
+     *
+     * @param userId 鐢ㄦ埛ID
+     * @return 鏉冮檺鍒楄〃
+     */
+    public List<String> selectMenuPermsByUserId(Long userId);
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鏌ヨ鑿滃崟
+     *
+     * @return 鑿滃崟鍒楄〃
+     */
+    public List<SysMenu> selectMenuTreeAll();
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鏌ヨ鑿滃崟
+     *
+     * @param userId 鐢ㄦ埛ID
+     * @return 鑿滃崟鍒楄〃
+     */
+    public List<SysMenu> selectMenuTreeByUserId(Long userId);
+
+    /**
+     * 鏍规嵁瑙掕壊ID鏌ヨ鑿滃崟鏍戜俊鎭�
+     * 
+     * @param roleId 瑙掕壊ID
+     * @param menuCheckStrictly 鑿滃崟鏍戦�夋嫨椤规槸鍚﹀叧鑱旀樉绀�
+     * @return 閫変腑鑿滃崟鍒楄〃
+     */
+    public List<Long> selectMenuListByRoleId(@Param("roleId") Long roleId, @Param("menuCheckStrictly") boolean menuCheckStrictly);
+
+    /**
+     * 鏍规嵁鑿滃崟ID鏌ヨ淇℃伅
+     *
+     * @param menuId 鑿滃崟ID
+     * @return 鑿滃崟淇℃伅
+     */
+    public SysMenu selectMenuById(Long menuId);
+
+    /**
+     * 鏄惁瀛樺湪鑿滃崟瀛愯妭鐐�
+     *
+     * @param menuId 鑿滃崟ID
+     * @return 缁撴灉
+     */
+    public int hasChildByMenuId(Long menuId);
+
+    /**
+     * 鏂板鑿滃崟淇℃伅
+     *
+     * @param menu 鑿滃崟淇℃伅
+     * @return 缁撴灉
+     */
+    public int insertMenu(SysMenu menu);
+
+    /**
+     * 淇敼鑿滃崟淇℃伅
+     *
+     * @param menu 鑿滃崟淇℃伅
+     * @return 缁撴灉
+     */
+    public int updateMenu(SysMenu menu);
+
+    /**
+     * 鍒犻櫎鑿滃崟绠$悊淇℃伅
+     *
+     * @param menuId 鑿滃崟ID
+     * @return 缁撴灉
+     */
+    public int deleteMenuById(Long menuId);
+
+    /**
+     * 鏍¢獙鑿滃崟鍚嶇О鏄惁鍞竴
+     *
+     * @param menuName 鑿滃崟鍚嶇О
+     * @param parentId 鐖惰彍鍗旾D
+     * @return 缁撴灉
+     */
+    public SysMenu checkMenuNameUnique(@Param("menuName") String menuName, @Param("parentId") Long parentId);
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/mapper/SysNoticeMapper.java b/jcdm-system/src/main/java/com/jcdm/system/mapper/SysNoticeMapper.java
new file mode 100644
index 0000000..94b3533
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/mapper/SysNoticeMapper.java
@@ -0,0 +1,60 @@
+package com.jcdm.system.mapper;
+
+import java.util.List;
+import com.jcdm.system.domain.SysNotice;
+
+/**
+ * 閫氱煡鍏憡琛� 鏁版嵁灞�
+ * 
+ * @author jc
+ */
+public interface SysNoticeMapper
+{
+    /**
+     * 鏌ヨ鍏憡淇℃伅
+     * 
+     * @param noticeId 鍏憡ID
+     * @return 鍏憡淇℃伅
+     */
+    public SysNotice selectNoticeById(Long noticeId);
+
+    /**
+     * 鏌ヨ鍏憡鍒楄〃
+     * 
+     * @param notice 鍏憡淇℃伅
+     * @return 鍏憡闆嗗悎
+     */
+    public List<SysNotice> selectNoticeList(SysNotice notice);
+
+    /**
+     * 鏂板鍏憡
+     * 
+     * @param notice 鍏憡淇℃伅
+     * @return 缁撴灉
+     */
+    public int insertNotice(SysNotice notice);
+
+    /**
+     * 淇敼鍏憡
+     * 
+     * @param notice 鍏憡淇℃伅
+     * @return 缁撴灉
+     */
+    public int updateNotice(SysNotice notice);
+
+    /**
+     * 鎵归噺鍒犻櫎鍏憡
+     * 
+     * @param noticeId 鍏憡ID
+     * @return 缁撴灉
+     */
+    public int deleteNoticeById(Long noticeId);
+
+    /**
+     * 鎵归噺鍒犻櫎鍏憡淇℃伅
+     * 
+     * @param noticeIds 闇�瑕佸垹闄ょ殑鍏憡ID
+     * @return 缁撴灉
+     */
+    public int deleteNoticeByIds(Long[] noticeIds);
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/mapper/SysOperLogMapper.java b/jcdm-system/src/main/java/com/jcdm/system/mapper/SysOperLogMapper.java
new file mode 100644
index 0000000..97437ae
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/mapper/SysOperLogMapper.java
@@ -0,0 +1,48 @@
+package com.jcdm.system.mapper;
+
+import java.util.List;
+import com.jcdm.system.domain.SysOperLog;
+
+/**
+ * 鎿嶄綔鏃ュ織 鏁版嵁灞�
+ * 
+ * @author jc
+ */
+public interface SysOperLogMapper
+{
+    /**
+     * 鏂板鎿嶄綔鏃ュ織
+     * 
+     * @param operLog 鎿嶄綔鏃ュ織瀵硅薄
+     */
+    public void insertOperlog(SysOperLog operLog);
+
+    /**
+     * 鏌ヨ绯荤粺鎿嶄綔鏃ュ織闆嗗悎
+     * 
+     * @param operLog 鎿嶄綔鏃ュ織瀵硅薄
+     * @return 鎿嶄綔鏃ュ織闆嗗悎
+     */
+    public List<SysOperLog> selectOperLogList(SysOperLog operLog);
+
+    /**
+     * 鎵归噺鍒犻櫎绯荤粺鎿嶄綔鏃ュ織
+     * 
+     * @param operIds 闇�瑕佸垹闄ょ殑鎿嶄綔鏃ュ織ID
+     * @return 缁撴灉
+     */
+    public int deleteOperLogByIds(Long[] operIds);
+
+    /**
+     * 鏌ヨ鎿嶄綔鏃ュ織璇︾粏
+     * 
+     * @param operId 鎿嶄綔ID
+     * @return 鎿嶄綔鏃ュ織瀵硅薄
+     */
+    public SysOperLog selectOperLogById(Long operId);
+
+    /**
+     * 娓呯┖鎿嶄綔鏃ュ織
+     */
+    public void cleanOperLog();
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/mapper/SysPostMapper.java b/jcdm-system/src/main/java/com/jcdm/system/mapper/SysPostMapper.java
new file mode 100644
index 0000000..c43009a
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/mapper/SysPostMapper.java
@@ -0,0 +1,99 @@
+package com.jcdm.system.mapper;
+
+import java.util.List;
+import com.jcdm.system.domain.SysPost;
+
+/**
+ * 宀椾綅淇℃伅 鏁版嵁灞�
+ * 
+ * @author jc
+ */
+public interface SysPostMapper
+{
+    /**
+     * 鏌ヨ宀椾綅鏁版嵁闆嗗悎
+     * 
+     * @param post 宀椾綅淇℃伅
+     * @return 宀椾綅鏁版嵁闆嗗悎
+     */
+    public List<SysPost> selectPostList(SysPost post);
+
+    /**
+     * 鏌ヨ鎵�鏈夊矖浣�
+     * 
+     * @return 宀椾綅鍒楄〃
+     */
+    public List<SysPost> selectPostAll();
+
+    /**
+     * 閫氳繃宀椾綅ID鏌ヨ宀椾綅淇℃伅
+     * 
+     * @param postId 宀椾綅ID
+     * @return 瑙掕壊瀵硅薄淇℃伅
+     */
+    public SysPost selectPostById(Long postId);
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鑾峰彇宀椾綅閫夋嫨妗嗗垪琛�
+     * 
+     * @param userId 鐢ㄦ埛ID
+     * @return 閫変腑宀椾綅ID鍒楄〃
+     */
+    public List<Long> selectPostListByUserId(Long userId);
+
+    /**
+     * 鏌ヨ鐢ㄦ埛鎵�灞炲矖浣嶇粍
+     * 
+     * @param userName 鐢ㄦ埛鍚�
+     * @return 缁撴灉
+     */
+    public List<SysPost> selectPostsByUserName(String userName);
+
+    /**
+     * 鍒犻櫎宀椾綅淇℃伅
+     * 
+     * @param postId 宀椾綅ID
+     * @return 缁撴灉
+     */
+    public int deletePostById(Long postId);
+
+    /**
+     * 鎵归噺鍒犻櫎宀椾綅淇℃伅
+     * 
+     * @param postIds 闇�瑕佸垹闄ょ殑宀椾綅ID
+     * @return 缁撴灉
+     */
+    public int deletePostByIds(Long[] postIds);
+
+    /**
+     * 淇敼宀椾綅淇℃伅
+     * 
+     * @param post 宀椾綅淇℃伅
+     * @return 缁撴灉
+     */
+    public int updatePost(SysPost post);
+
+    /**
+     * 鏂板宀椾綅淇℃伅
+     * 
+     * @param post 宀椾綅淇℃伅
+     * @return 缁撴灉
+     */
+    public int insertPost(SysPost post);
+
+    /**
+     * 鏍¢獙宀椾綅鍚嶇О
+     * 
+     * @param postName 宀椾綅鍚嶇О
+     * @return 缁撴灉
+     */
+    public SysPost checkPostNameUnique(String postName);
+
+    /**
+     * 鏍¢獙宀椾綅缂栫爜
+     * 
+     * @param postCode 宀椾綅缂栫爜
+     * @return 缁撴灉
+     */
+    public SysPost checkPostCodeUnique(String postCode);
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/mapper/SysRoleDeptMapper.java b/jcdm-system/src/main/java/com/jcdm/system/mapper/SysRoleDeptMapper.java
new file mode 100644
index 0000000..81404da
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/mapper/SysRoleDeptMapper.java
@@ -0,0 +1,44 @@
+package com.jcdm.system.mapper;
+
+import java.util.List;
+import com.jcdm.system.domain.SysRoleDept;
+
+/**
+ * 瑙掕壊涓庨儴闂ㄥ叧鑱旇〃 鏁版嵁灞�
+ * 
+ * @author jc
+ */
+public interface SysRoleDeptMapper
+{
+    /**
+     * 閫氳繃瑙掕壊ID鍒犻櫎瑙掕壊鍜岄儴闂ㄥ叧鑱�
+     * 
+     * @param roleId 瑙掕壊ID
+     * @return 缁撴灉
+     */
+    public int deleteRoleDeptByRoleId(Long roleId);
+
+    /**
+     * 鎵归噺鍒犻櫎瑙掕壊閮ㄩ棬鍏宠仈淇℃伅
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁ID
+     * @return 缁撴灉
+     */
+    public int deleteRoleDept(Long[] ids);
+
+    /**
+     * 鏌ヨ閮ㄩ棬浣跨敤鏁伴噺
+     * 
+     * @param deptId 閮ㄩ棬ID
+     * @return 缁撴灉
+     */
+    public int selectCountRoleDeptByDeptId(Long deptId);
+
+    /**
+     * 鎵归噺鏂板瑙掕壊閮ㄩ棬淇℃伅
+     * 
+     * @param roleDeptList 瑙掕壊閮ㄩ棬鍒楄〃
+     * @return 缁撴灉
+     */
+    public int batchRoleDept(List<SysRoleDept> roleDeptList);
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/mapper/SysRoleMapper.java b/jcdm-system/src/main/java/com/jcdm/system/mapper/SysRoleMapper.java
new file mode 100644
index 0000000..41be7b0
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/mapper/SysRoleMapper.java
@@ -0,0 +1,107 @@
+package com.jcdm.system.mapper;
+
+import java.util.List;
+import com.jcdm.common.core.domain.entity.SysRole;
+
+/**
+ * 瑙掕壊琛� 鏁版嵁灞�
+ * 
+ * @author jc
+ */
+public interface SysRoleMapper
+{
+    /**
+     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瑙掕壊鏁版嵁
+     * 
+     * @param role 瑙掕壊淇℃伅
+     * @return 瑙掕壊鏁版嵁闆嗗悎淇℃伅
+     */
+    public List<SysRole> selectRoleList(SysRole role);
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鏌ヨ瑙掕壊
+     * 
+     * @param userId 鐢ㄦ埛ID
+     * @return 瑙掕壊鍒楄〃
+     */
+    public List<SysRole> selectRolePermissionByUserId(Long userId);
+
+    /**
+     * 鏌ヨ鎵�鏈夎鑹�
+     * 
+     * @return 瑙掕壊鍒楄〃
+     */
+    public List<SysRole> selectRoleAll();
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鑾峰彇瑙掕壊閫夋嫨妗嗗垪琛�
+     * 
+     * @param userId 鐢ㄦ埛ID
+     * @return 閫変腑瑙掕壊ID鍒楄〃
+     */
+    public List<Long> selectRoleListByUserId(Long userId);
+
+    /**
+     * 閫氳繃瑙掕壊ID鏌ヨ瑙掕壊
+     * 
+     * @param roleId 瑙掕壊ID
+     * @return 瑙掕壊瀵硅薄淇℃伅
+     */
+    public SysRole selectRoleById(Long roleId);
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鏌ヨ瑙掕壊
+     * 
+     * @param userName 鐢ㄦ埛鍚�
+     * @return 瑙掕壊鍒楄〃
+     */
+    public List<SysRole> selectRolesByUserName(String userName);
+
+    /**
+     * 鏍¢獙瑙掕壊鍚嶇О鏄惁鍞竴
+     * 
+     * @param roleName 瑙掕壊鍚嶇О
+     * @return 瑙掕壊淇℃伅
+     */
+    public SysRole checkRoleNameUnique(String roleName);
+
+    /**
+     * 鏍¢獙瑙掕壊鏉冮檺鏄惁鍞竴
+     * 
+     * @param roleKey 瑙掕壊鏉冮檺
+     * @return 瑙掕壊淇℃伅
+     */
+    public SysRole checkRoleKeyUnique(String roleKey);
+
+    /**
+     * 淇敼瑙掕壊淇℃伅
+     * 
+     * @param role 瑙掕壊淇℃伅
+     * @return 缁撴灉
+     */
+    public int updateRole(SysRole role);
+
+    /**
+     * 鏂板瑙掕壊淇℃伅
+     * 
+     * @param role 瑙掕壊淇℃伅
+     * @return 缁撴灉
+     */
+    public int insertRole(SysRole role);
+
+    /**
+     * 閫氳繃瑙掕壊ID鍒犻櫎瑙掕壊
+     * 
+     * @param roleId 瑙掕壊ID
+     * @return 缁撴灉
+     */
+    public int deleteRoleById(Long roleId);
+
+    /**
+     * 鎵归噺鍒犻櫎瑙掕壊淇℃伅
+     * 
+     * @param roleIds 闇�瑕佸垹闄ょ殑瑙掕壊ID
+     * @return 缁撴灉
+     */
+    public int deleteRoleByIds(Long[] roleIds);
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/mapper/SysRoleMenuMapper.java b/jcdm-system/src/main/java/com/jcdm/system/mapper/SysRoleMenuMapper.java
new file mode 100644
index 0000000..77c12ff
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/mapper/SysRoleMenuMapper.java
@@ -0,0 +1,44 @@
+package com.jcdm.system.mapper;
+
+import java.util.List;
+import com.jcdm.system.domain.SysRoleMenu;
+
+/**
+ * 瑙掕壊涓庤彍鍗曞叧鑱旇〃 鏁版嵁灞�
+ * 
+ * @author jc
+ */
+public interface SysRoleMenuMapper
+{
+    /**
+     * 鏌ヨ鑿滃崟浣跨敤鏁伴噺
+     * 
+     * @param menuId 鑿滃崟ID
+     * @return 缁撴灉
+     */
+    public int checkMenuExistRole(Long menuId);
+
+    /**
+     * 閫氳繃瑙掕壊ID鍒犻櫎瑙掕壊鍜岃彍鍗曞叧鑱�
+     * 
+     * @param roleId 瑙掕壊ID
+     * @return 缁撴灉
+     */
+    public int deleteRoleMenuByRoleId(Long roleId);
+
+    /**
+     * 鎵归噺鍒犻櫎瑙掕壊鑿滃崟鍏宠仈淇℃伅
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁ID
+     * @return 缁撴灉
+     */
+    public int deleteRoleMenu(Long[] ids);
+
+    /**
+     * 鎵归噺鏂板瑙掕壊鑿滃崟淇℃伅
+     * 
+     * @param roleMenuList 瑙掕壊鑿滃崟鍒楄〃
+     * @return 缁撴灉
+     */
+    public int batchRoleMenu(List<SysRoleMenu> roleMenuList);
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/mapper/SysUserMapper.java b/jcdm-system/src/main/java/com/jcdm/system/mapper/SysUserMapper.java
new file mode 100644
index 0000000..cf92a1a
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/mapper/SysUserMapper.java
@@ -0,0 +1,127 @@
+package com.jcdm.system.mapper;
+
+import java.util.List;
+import org.apache.ibatis.annotations.Param;
+import com.jcdm.common.core.domain.entity.SysUser;
+
+/**
+ * 鐢ㄦ埛琛� 鏁版嵁灞�
+ * 
+ * @author jc
+ */
+public interface SysUserMapper
+{
+    /**
+     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ鐢ㄦ埛鍒楄〃
+     * 
+     * @param sysUser 鐢ㄦ埛淇℃伅
+     * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
+     */
+    public List<SysUser> selectUserList(SysUser sysUser);
+
+    /**
+     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ宸查厤鐢ㄦ埛瑙掕壊鍒楄〃
+     * 
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
+     */
+    public List<SysUser> selectAllocatedList(SysUser user);
+
+    /**
+     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ鏈垎閰嶇敤鎴疯鑹插垪琛�
+     * 
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
+     */
+    public List<SysUser> selectUnallocatedList(SysUser user);
+
+    /**
+     * 閫氳繃鐢ㄦ埛鍚嶆煡璇㈢敤鎴�
+     * 
+     * @param userName 鐢ㄦ埛鍚�
+     * @return 鐢ㄦ埛瀵硅薄淇℃伅
+     */
+    public SysUser selectUserByUserName(String userName);
+
+    /**
+     * 閫氳繃鐢ㄦ埛ID鏌ヨ鐢ㄦ埛
+     * 
+     * @param userId 鐢ㄦ埛ID
+     * @return 鐢ㄦ埛瀵硅薄淇℃伅
+     */
+    public SysUser selectUserById(Long userId);
+
+    /**
+     * 鏂板鐢ㄦ埛淇℃伅
+     * 
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 缁撴灉
+     */
+    public int insertUser(SysUser user);
+
+    /**
+     * 淇敼鐢ㄦ埛淇℃伅
+     * 
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 缁撴灉
+     */
+    public int updateUser(SysUser user);
+
+    /**
+     * 淇敼鐢ㄦ埛澶村儚
+     * 
+     * @param userName 鐢ㄦ埛鍚�
+     * @param avatar 澶村儚鍦板潃
+     * @return 缁撴灉
+     */
+    public int updateUserAvatar(@Param("userName") String userName, @Param("avatar") String avatar);
+
+    /**
+     * 閲嶇疆鐢ㄦ埛瀵嗙爜
+     * 
+     * @param userName 鐢ㄦ埛鍚�
+     * @param password 瀵嗙爜
+     * @return 缁撴灉
+     */
+    public int resetUserPwd(@Param("userName") String userName, @Param("password") String password);
+
+    /**
+     * 閫氳繃鐢ㄦ埛ID鍒犻櫎鐢ㄦ埛
+     * 
+     * @param userId 鐢ㄦ埛ID
+     * @return 缁撴灉
+     */
+    public int deleteUserById(Long userId);
+
+    /**
+     * 鎵归噺鍒犻櫎鐢ㄦ埛淇℃伅
+     * 
+     * @param userIds 闇�瑕佸垹闄ょ殑鐢ㄦ埛ID
+     * @return 缁撴灉
+     */
+    public int deleteUserByIds(Long[] userIds);
+
+    /**
+     * 鏍¢獙鐢ㄦ埛鍚嶇О鏄惁鍞竴
+     * 
+     * @param userName 鐢ㄦ埛鍚嶇О
+     * @return 缁撴灉
+     */
+    public SysUser checkUserNameUnique(String userName);
+
+    /**
+     * 鏍¢獙鎵嬫満鍙风爜鏄惁鍞竴
+     *
+     * @param phonenumber 鎵嬫満鍙风爜
+     * @return 缁撴灉
+     */
+    public SysUser checkPhoneUnique(String phonenumber);
+
+    /**
+     * 鏍¢獙email鏄惁鍞竴
+     *
+     * @param email 鐢ㄦ埛閭
+     * @return 缁撴灉
+     */
+    public SysUser checkEmailUnique(String email);
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/mapper/SysUserPostMapper.java b/jcdm-system/src/main/java/com/jcdm/system/mapper/SysUserPostMapper.java
new file mode 100644
index 0000000..43c4e68
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/mapper/SysUserPostMapper.java
@@ -0,0 +1,44 @@
+package com.jcdm.system.mapper;
+
+import java.util.List;
+import com.jcdm.system.domain.SysUserPost;
+
+/**
+ * 鐢ㄦ埛涓庡矖浣嶅叧鑱旇〃 鏁版嵁灞�
+ * 
+ * @author jc
+ */
+public interface SysUserPostMapper
+{
+    /**
+     * 閫氳繃鐢ㄦ埛ID鍒犻櫎鐢ㄦ埛鍜屽矖浣嶅叧鑱�
+     * 
+     * @param userId 鐢ㄦ埛ID
+     * @return 缁撴灉
+     */
+    public int deleteUserPostByUserId(Long userId);
+
+    /**
+     * 閫氳繃宀椾綅ID鏌ヨ宀椾綅浣跨敤鏁伴噺
+     * 
+     * @param postId 宀椾綅ID
+     * @return 缁撴灉
+     */
+    public int countUserPostById(Long postId);
+
+    /**
+     * 鎵归噺鍒犻櫎鐢ㄦ埛鍜屽矖浣嶅叧鑱�
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁ID
+     * @return 缁撴灉
+     */
+    public int deleteUserPost(Long[] ids);
+
+    /**
+     * 鎵归噺鏂板鐢ㄦ埛宀椾綅淇℃伅
+     * 
+     * @param userPostList 鐢ㄦ埛宀椾綅鍒楄〃
+     * @return 缁撴灉
+     */
+    public int batchUserPost(List<SysUserPost> userPostList);
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/mapper/SysUserRoleMapper.java b/jcdm-system/src/main/java/com/jcdm/system/mapper/SysUserRoleMapper.java
new file mode 100644
index 0000000..a0c628e
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/mapper/SysUserRoleMapper.java
@@ -0,0 +1,62 @@
+package com.jcdm.system.mapper;
+
+import java.util.List;
+import org.apache.ibatis.annotations.Param;
+import com.jcdm.system.domain.SysUserRole;
+
+/**
+ * 鐢ㄦ埛涓庤鑹插叧鑱旇〃 鏁版嵁灞�
+ * 
+ * @author jc
+ */
+public interface SysUserRoleMapper
+{
+    /**
+     * 閫氳繃鐢ㄦ埛ID鍒犻櫎鐢ㄦ埛鍜岃鑹插叧鑱�
+     * 
+     * @param userId 鐢ㄦ埛ID
+     * @return 缁撴灉
+     */
+    public int deleteUserRoleByUserId(Long userId);
+
+    /**
+     * 鎵归噺鍒犻櫎鐢ㄦ埛鍜岃鑹插叧鑱�
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁ID
+     * @return 缁撴灉
+     */
+    public int deleteUserRole(Long[] ids);
+
+    /**
+     * 閫氳繃瑙掕壊ID鏌ヨ瑙掕壊浣跨敤鏁伴噺
+     * 
+     * @param roleId 瑙掕壊ID
+     * @return 缁撴灉
+     */
+    public int countUserRoleByRoleId(Long roleId);
+
+    /**
+     * 鎵归噺鏂板鐢ㄦ埛瑙掕壊淇℃伅
+     * 
+     * @param userRoleList 鐢ㄦ埛瑙掕壊鍒楄〃
+     * @return 缁撴灉
+     */
+    public int batchUserRole(List<SysUserRole> userRoleList);
+
+    /**
+     * 鍒犻櫎鐢ㄦ埛鍜岃鑹插叧鑱斾俊鎭�
+     * 
+     * @param userRole 鐢ㄦ埛鍜岃鑹插叧鑱斾俊鎭�
+     * @return 缁撴灉
+     */
+    public int deleteUserRoleInfo(SysUserRole userRole);
+
+    /**
+     * 鎵归噺鍙栨秷鎺堟潈鐢ㄦ埛瑙掕壊
+     * 
+     * @param roleId 瑙掕壊ID
+     * @param userIds 闇�瑕佸垹闄ょ殑鐢ㄦ埛鏁版嵁ID
+     * @return 缁撴灉
+     */
+    public int deleteUserRoleInfos(@Param("roleId") Long roleId, @Param("userIds") Long[] userIds);
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/service/ISysConfigService.java b/jcdm-system/src/main/java/com/jcdm/system/service/ISysConfigService.java
new file mode 100644
index 0000000..e79322f
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/service/ISysConfigService.java
@@ -0,0 +1,89 @@
+package com.jcdm.system.service;
+
+import java.util.List;
+import com.jcdm.system.domain.SysConfig;
+
+/**
+ * 鍙傛暟閰嶇疆 鏈嶅姟灞�
+ * 
+ * @author jc
+ */
+public interface ISysConfigService
+{
+    /**
+     * 鏌ヨ鍙傛暟閰嶇疆淇℃伅
+     * 
+     * @param configId 鍙傛暟閰嶇疆ID
+     * @return 鍙傛暟閰嶇疆淇℃伅
+     */
+    public SysConfig selectConfigById(Long configId);
+
+    /**
+     * 鏍规嵁閿悕鏌ヨ鍙傛暟閰嶇疆淇℃伅
+     * 
+     * @param configKey 鍙傛暟閿悕
+     * @return 鍙傛暟閿��
+     */
+    public String selectConfigByKey(String configKey);
+
+    /**
+     * 鑾峰彇楠岃瘉鐮佸紑鍏�
+     * 
+     * @return true寮�鍚紝false鍏抽棴
+     */
+    public boolean selectCaptchaEnabled();
+
+    /**
+     * 鏌ヨ鍙傛暟閰嶇疆鍒楄〃
+     * 
+     * @param config 鍙傛暟閰嶇疆淇℃伅
+     * @return 鍙傛暟閰嶇疆闆嗗悎
+     */
+    public List<SysConfig> selectConfigList(SysConfig config);
+
+    /**
+     * 鏂板鍙傛暟閰嶇疆
+     * 
+     * @param config 鍙傛暟閰嶇疆淇℃伅
+     * @return 缁撴灉
+     */
+    public int insertConfig(SysConfig config);
+
+    /**
+     * 淇敼鍙傛暟閰嶇疆
+     * 
+     * @param config 鍙傛暟閰嶇疆淇℃伅
+     * @return 缁撴灉
+     */
+    public int updateConfig(SysConfig config);
+
+    /**
+     * 鎵归噺鍒犻櫎鍙傛暟淇℃伅
+     * 
+     * @param configIds 闇�瑕佸垹闄ょ殑鍙傛暟ID
+     */
+    public void deleteConfigByIds(Long[] configIds);
+
+    /**
+     * 鍔犺浇鍙傛暟缂撳瓨鏁版嵁
+     */
+    public void loadingConfigCache();
+
+    /**
+     * 娓呯┖鍙傛暟缂撳瓨鏁版嵁
+     */
+    public void clearConfigCache();
+
+    /**
+     * 閲嶇疆鍙傛暟缂撳瓨鏁版嵁
+     */
+    public void resetConfigCache();
+
+    /**
+     * 鏍¢獙鍙傛暟閿悕鏄惁鍞竴
+     * 
+     * @param config 鍙傛暟淇℃伅
+     * @return 缁撴灉
+     */
+    public boolean checkConfigKeyUnique(SysConfig config);
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/service/ISysDeptService.java b/jcdm-system/src/main/java/com/jcdm/system/service/ISysDeptService.java
new file mode 100644
index 0000000..65f59a5
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/service/ISysDeptService.java
@@ -0,0 +1,124 @@
+package com.jcdm.system.service;
+
+import java.util.List;
+import com.jcdm.common.core.domain.TreeSelect;
+import com.jcdm.common.core.domain.entity.SysDept;
+
+/**
+ * 閮ㄩ棬绠$悊 鏈嶅姟灞�
+ * 
+ * @author jc
+ */
+public interface ISysDeptService
+{
+    /**
+     * 鏌ヨ閮ㄩ棬绠$悊鏁版嵁
+     * 
+     * @param dept 閮ㄩ棬淇℃伅
+     * @return 閮ㄩ棬淇℃伅闆嗗悎
+     */
+    public List<SysDept> selectDeptList(SysDept dept);
+
+    /**
+     * 鏌ヨ閮ㄩ棬鏍戠粨鏋勪俊鎭�
+     * 
+     * @param dept 閮ㄩ棬淇℃伅
+     * @return 閮ㄩ棬鏍戜俊鎭泦鍚�
+     */
+    public List<TreeSelect> selectDeptTreeList(SysDept dept);
+
+    /**
+     * 鏋勫缓鍓嶇鎵�闇�瑕佹爲缁撴瀯
+     * 
+     * @param depts 閮ㄩ棬鍒楄〃
+     * @return 鏍戠粨鏋勫垪琛�
+     */
+    public List<SysDept> buildDeptTree(List<SysDept> depts);
+
+    /**
+     * 鏋勫缓鍓嶇鎵�闇�瑕佷笅鎷夋爲缁撴瀯
+     * 
+     * @param depts 閮ㄩ棬鍒楄〃
+     * @return 涓嬫媺鏍戠粨鏋勫垪琛�
+     */
+    public List<TreeSelect> buildDeptTreeSelect(List<SysDept> depts);
+
+    /**
+     * 鏍规嵁瑙掕壊ID鏌ヨ閮ㄩ棬鏍戜俊鎭�
+     * 
+     * @param roleId 瑙掕壊ID
+     * @return 閫変腑閮ㄩ棬鍒楄〃
+     */
+    public List<Long> selectDeptListByRoleId(Long roleId);
+
+    /**
+     * 鏍规嵁閮ㄩ棬ID鏌ヨ淇℃伅
+     * 
+     * @param deptId 閮ㄩ棬ID
+     * @return 閮ㄩ棬淇℃伅
+     */
+    public SysDept selectDeptById(Long deptId);
+
+    /**
+     * 鏍规嵁ID鏌ヨ鎵�鏈夊瓙閮ㄩ棬锛堟甯哥姸鎬侊級
+     * 
+     * @param deptId 閮ㄩ棬ID
+     * @return 瀛愰儴闂ㄦ暟
+     */
+    public int selectNormalChildrenDeptById(Long deptId);
+
+    /**
+     * 鏄惁瀛樺湪閮ㄩ棬瀛愯妭鐐�
+     * 
+     * @param deptId 閮ㄩ棬ID
+     * @return 缁撴灉
+     */
+    public boolean hasChildByDeptId(Long deptId);
+
+    /**
+     * 鏌ヨ閮ㄩ棬鏄惁瀛樺湪鐢ㄦ埛
+     * 
+     * @param deptId 閮ㄩ棬ID
+     * @return 缁撴灉 true 瀛樺湪 false 涓嶅瓨鍦�
+     */
+    public boolean checkDeptExistUser(Long deptId);
+
+    /**
+     * 鏍¢獙閮ㄩ棬鍚嶇О鏄惁鍞竴
+     * 
+     * @param dept 閮ㄩ棬淇℃伅
+     * @return 缁撴灉
+     */
+    public boolean checkDeptNameUnique(SysDept dept);
+
+    /**
+     * 鏍¢獙閮ㄩ棬鏄惁鏈夋暟鎹潈闄�
+     * 
+     * @param deptId 閮ㄩ棬id
+     */
+    public void checkDeptDataScope(Long deptId);
+
+    /**
+     * 鏂板淇濆瓨閮ㄩ棬淇℃伅
+     * 
+     * @param dept 閮ㄩ棬淇℃伅
+     * @return 缁撴灉
+     */
+    public int insertDept(SysDept dept);
+
+    /**
+     * 淇敼淇濆瓨閮ㄩ棬淇℃伅
+     * 
+     * @param dept 閮ㄩ棬淇℃伅
+     * @return 缁撴灉
+     */
+    public int updateDept(SysDept dept);
+
+    /**
+     * 鍒犻櫎閮ㄩ棬绠$悊淇℃伅
+     * 
+     * @param deptId 閮ㄩ棬ID
+     * @return 缁撴灉
+     */
+    public int deleteDeptById(Long deptId);
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/service/ISysDictDataService.java b/jcdm-system/src/main/java/com/jcdm/system/service/ISysDictDataService.java
new file mode 100644
index 0000000..70ce35f
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/service/ISysDictDataService.java
@@ -0,0 +1,60 @@
+package com.jcdm.system.service;
+
+import java.util.List;
+import com.jcdm.common.core.domain.entity.SysDictData;
+
+/**
+ * 瀛楀吀 涓氬姟灞�
+ * 
+ * @author jc
+ */
+public interface ISysDictDataService
+{
+    /**
+     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瀛楀吀鏁版嵁
+     * 
+     * @param dictData 瀛楀吀鏁版嵁淇℃伅
+     * @return 瀛楀吀鏁版嵁闆嗗悎淇℃伅
+     */
+    public List<SysDictData> selectDictDataList(SysDictData dictData);
+
+    /**
+     * 鏍规嵁瀛楀吀绫诲瀷鍜屽瓧鍏搁敭鍊兼煡璇㈠瓧鍏告暟鎹俊鎭�
+     * 
+     * @param dictType 瀛楀吀绫诲瀷
+     * @param dictValue 瀛楀吀閿��
+     * @return 瀛楀吀鏍囩
+     */
+    public String selectDictLabel(String dictType, String dictValue);
+
+    /**
+     * 鏍规嵁瀛楀吀鏁版嵁ID鏌ヨ淇℃伅
+     * 
+     * @param dictCode 瀛楀吀鏁版嵁ID
+     * @return 瀛楀吀鏁版嵁
+     */
+    public SysDictData selectDictDataById(Long dictCode);
+
+    /**
+     * 鎵归噺鍒犻櫎瀛楀吀鏁版嵁淇℃伅
+     * 
+     * @param dictCodes 闇�瑕佸垹闄ょ殑瀛楀吀鏁版嵁ID
+     */
+    public void deleteDictDataByIds(Long[] dictCodes);
+
+    /**
+     * 鏂板淇濆瓨瀛楀吀鏁版嵁淇℃伅
+     * 
+     * @param dictData 瀛楀吀鏁版嵁淇℃伅
+     * @return 缁撴灉
+     */
+    public int insertDictData(SysDictData dictData);
+
+    /**
+     * 淇敼淇濆瓨瀛楀吀鏁版嵁淇℃伅
+     * 
+     * @param dictData 瀛楀吀鏁版嵁淇℃伅
+     * @return 缁撴灉
+     */
+    public int updateDictData(SysDictData dictData);
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/service/ISysDictTypeService.java b/jcdm-system/src/main/java/com/jcdm/system/service/ISysDictTypeService.java
new file mode 100644
index 0000000..44146ee
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/service/ISysDictTypeService.java
@@ -0,0 +1,98 @@
+package com.jcdm.system.service;
+
+import java.util.List;
+import com.jcdm.common.core.domain.entity.SysDictData;
+import com.jcdm.common.core.domain.entity.SysDictType;
+
+/**
+ * 瀛楀吀 涓氬姟灞�
+ * 
+ * @author jc
+ */
+public interface ISysDictTypeService
+{
+    /**
+     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瀛楀吀绫诲瀷
+     * 
+     * @param dictType 瀛楀吀绫诲瀷淇℃伅
+     * @return 瀛楀吀绫诲瀷闆嗗悎淇℃伅
+     */
+    public List<SysDictType> selectDictTypeList(SysDictType dictType);
+
+    /**
+     * 鏍规嵁鎵�鏈夊瓧鍏哥被鍨�
+     * 
+     * @return 瀛楀吀绫诲瀷闆嗗悎淇℃伅
+     */
+    public List<SysDictType> selectDictTypeAll();
+
+    /**
+     * 鏍规嵁瀛楀吀绫诲瀷鏌ヨ瀛楀吀鏁版嵁
+     * 
+     * @param dictType 瀛楀吀绫诲瀷
+     * @return 瀛楀吀鏁版嵁闆嗗悎淇℃伅
+     */
+    public List<SysDictData> selectDictDataByType(String dictType);
+
+    /**
+     * 鏍规嵁瀛楀吀绫诲瀷ID鏌ヨ淇℃伅
+     * 
+     * @param dictId 瀛楀吀绫诲瀷ID
+     * @return 瀛楀吀绫诲瀷
+     */
+    public SysDictType selectDictTypeById(Long dictId);
+
+    /**
+     * 鏍规嵁瀛楀吀绫诲瀷鏌ヨ淇℃伅
+     * 
+     * @param dictType 瀛楀吀绫诲瀷
+     * @return 瀛楀吀绫诲瀷
+     */
+    public SysDictType selectDictTypeByType(String dictType);
+
+    /**
+     * 鎵归噺鍒犻櫎瀛楀吀淇℃伅
+     * 
+     * @param dictIds 闇�瑕佸垹闄ょ殑瀛楀吀ID
+     */
+    public void deleteDictTypeByIds(Long[] dictIds);
+
+    /**
+     * 鍔犺浇瀛楀吀缂撳瓨鏁版嵁
+     */
+    public void loadingDictCache();
+
+    /**
+     * 娓呯┖瀛楀吀缂撳瓨鏁版嵁
+     */
+    public void clearDictCache();
+
+    /**
+     * 閲嶇疆瀛楀吀缂撳瓨鏁版嵁
+     */
+    public void resetDictCache();
+
+    /**
+     * 鏂板淇濆瓨瀛楀吀绫诲瀷淇℃伅
+     * 
+     * @param dictType 瀛楀吀绫诲瀷淇℃伅
+     * @return 缁撴灉
+     */
+    public int insertDictType(SysDictType dictType);
+
+    /**
+     * 淇敼淇濆瓨瀛楀吀绫诲瀷淇℃伅
+     * 
+     * @param dictType 瀛楀吀绫诲瀷淇℃伅
+     * @return 缁撴灉
+     */
+    public int updateDictType(SysDictType dictType);
+
+    /**
+     * 鏍¢獙瀛楀吀绫诲瀷绉版槸鍚﹀敮涓�
+     * 
+     * @param dictType 瀛楀吀绫诲瀷
+     * @return 缁撴灉
+     */
+    public boolean checkDictTypeUnique(SysDictType dictType);
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/service/ISysLogininforService.java b/jcdm-system/src/main/java/com/jcdm/system/service/ISysLogininforService.java
new file mode 100644
index 0000000..08aa121
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/service/ISysLogininforService.java
@@ -0,0 +1,40 @@
+package com.jcdm.system.service;
+
+import java.util.List;
+import com.jcdm.system.domain.SysLogininfor;
+
+/**
+ * 绯荤粺璁块棶鏃ュ織鎯呭喌淇℃伅 鏈嶅姟灞�
+ * 
+ * @author jc
+ */
+public interface ISysLogininforService
+{
+    /**
+     * 鏂板绯荤粺鐧诲綍鏃ュ織
+     * 
+     * @param logininfor 璁块棶鏃ュ織瀵硅薄
+     */
+    public void insertLogininfor(SysLogininfor logininfor);
+
+    /**
+     * 鏌ヨ绯荤粺鐧诲綍鏃ュ織闆嗗悎
+     * 
+     * @param logininfor 璁块棶鏃ュ織瀵硅薄
+     * @return 鐧诲綍璁板綍闆嗗悎
+     */
+    public List<SysLogininfor> selectLogininforList(SysLogininfor logininfor);
+
+    /**
+     * 鎵归噺鍒犻櫎绯荤粺鐧诲綍鏃ュ織
+     * 
+     * @param infoIds 闇�瑕佸垹闄ょ殑鐧诲綍鏃ュ織ID
+     * @return 缁撴灉
+     */
+    public int deleteLogininforByIds(Long[] infoIds);
+
+    /**
+     * 娓呯┖绯荤粺鐧诲綍鏃ュ織
+     */
+    public void cleanLogininfor();
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/service/ISysMenuService.java b/jcdm-system/src/main/java/com/jcdm/system/service/ISysMenuService.java
new file mode 100644
index 0000000..eea49ee
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/service/ISysMenuService.java
@@ -0,0 +1,144 @@
+package com.jcdm.system.service;
+
+import java.util.List;
+import java.util.Set;
+import com.jcdm.common.core.domain.TreeSelect;
+import com.jcdm.common.core.domain.entity.SysMenu;
+import com.jcdm.system.domain.vo.RouterVo;
+
+/**
+ * 鑿滃崟 涓氬姟灞�
+ * 
+ * @author jc
+ */
+public interface ISysMenuService
+{
+    /**
+     * 鏍规嵁鐢ㄦ埛鏌ヨ绯荤粺鑿滃崟鍒楄〃
+     * 
+     * @param userId 鐢ㄦ埛ID
+     * @return 鑿滃崟鍒楄〃
+     */
+    public List<SysMenu> selectMenuList(Long userId);
+
+    /**
+     * 鏍规嵁鐢ㄦ埛鏌ヨ绯荤粺鑿滃崟鍒楄〃
+     * 
+     * @param menu 鑿滃崟淇℃伅
+     * @param userId 鐢ㄦ埛ID
+     * @return 鑿滃崟鍒楄〃
+     */
+    public List<SysMenu> selectMenuList(SysMenu menu, Long userId);
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鏌ヨ鏉冮檺
+     * 
+     * @param userId 鐢ㄦ埛ID
+     * @return 鏉冮檺鍒楄〃
+     */
+    public Set<String> selectMenuPermsByUserId(Long userId);
+
+    /**
+     * 鏍规嵁瑙掕壊ID鏌ヨ鏉冮檺
+     * 
+     * @param roleId 瑙掕壊ID
+     * @return 鏉冮檺鍒楄〃
+     */
+    public Set<String> selectMenuPermsByRoleId(Long roleId);
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鏌ヨ鑿滃崟鏍戜俊鎭�
+     * 
+     * @param userId 鐢ㄦ埛ID
+     * @return 鑿滃崟鍒楄〃
+     */
+    public List<SysMenu> selectMenuTreeByUserId(Long userId);
+
+    /**
+     * 鏍规嵁瑙掕壊ID鏌ヨ鑿滃崟鏍戜俊鎭�
+     * 
+     * @param roleId 瑙掕壊ID
+     * @return 閫変腑鑿滃崟鍒楄〃
+     */
+    public List<Long> selectMenuListByRoleId(Long roleId);
+
+    /**
+     * 鏋勫缓鍓嶇璺敱鎵�闇�瑕佺殑鑿滃崟
+     * 
+     * @param menus 鑿滃崟鍒楄〃
+     * @return 璺敱鍒楄〃
+     */
+    public List<RouterVo> buildMenus(List<SysMenu> menus);
+
+    /**
+     * 鏋勫缓鍓嶇鎵�闇�瑕佹爲缁撴瀯
+     * 
+     * @param menus 鑿滃崟鍒楄〃
+     * @return 鏍戠粨鏋勫垪琛�
+     */
+    public List<SysMenu> buildMenuTree(List<SysMenu> menus);
+
+    /**
+     * 鏋勫缓鍓嶇鎵�闇�瑕佷笅鎷夋爲缁撴瀯
+     * 
+     * @param menus 鑿滃崟鍒楄〃
+     * @return 涓嬫媺鏍戠粨鏋勫垪琛�
+     */
+    public List<TreeSelect> buildMenuTreeSelect(List<SysMenu> menus);
+
+    /**
+     * 鏍规嵁鑿滃崟ID鏌ヨ淇℃伅
+     * 
+     * @param menuId 鑿滃崟ID
+     * @return 鑿滃崟淇℃伅
+     */
+    public SysMenu selectMenuById(Long menuId);
+
+    /**
+     * 鏄惁瀛樺湪鑿滃崟瀛愯妭鐐�
+     * 
+     * @param menuId 鑿滃崟ID
+     * @return 缁撴灉 true 瀛樺湪 false 涓嶅瓨鍦�
+     */
+    public boolean hasChildByMenuId(Long menuId);
+
+    /**
+     * 鏌ヨ鑿滃崟鏄惁瀛樺湪瑙掕壊
+     * 
+     * @param menuId 鑿滃崟ID
+     * @return 缁撴灉 true 瀛樺湪 false 涓嶅瓨鍦�
+     */
+    public boolean checkMenuExistRole(Long menuId);
+
+    /**
+     * 鏂板淇濆瓨鑿滃崟淇℃伅
+     * 
+     * @param menu 鑿滃崟淇℃伅
+     * @return 缁撴灉
+     */
+    public int insertMenu(SysMenu menu);
+
+    /**
+     * 淇敼淇濆瓨鑿滃崟淇℃伅
+     * 
+     * @param menu 鑿滃崟淇℃伅
+     * @return 缁撴灉
+     */
+    public int updateMenu(SysMenu menu);
+
+    /**
+     * 鍒犻櫎鑿滃崟绠$悊淇℃伅
+     * 
+     * @param menuId 鑿滃崟ID
+     * @return 缁撴灉
+     */
+    public int deleteMenuById(Long menuId);
+
+    /**
+     * 鏍¢獙鑿滃崟鍚嶇О鏄惁鍞竴
+     * 
+     * @param menu 鑿滃崟淇℃伅
+     * @return 缁撴灉
+     */
+    public boolean checkMenuNameUnique(SysMenu menu);
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/service/ISysNoticeService.java b/jcdm-system/src/main/java/com/jcdm/system/service/ISysNoticeService.java
new file mode 100644
index 0000000..83abb78
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/service/ISysNoticeService.java
@@ -0,0 +1,60 @@
+package com.jcdm.system.service;
+
+import java.util.List;
+import com.jcdm.system.domain.SysNotice;
+
+/**
+ * 鍏憡 鏈嶅姟灞�
+ * 
+ * @author jc
+ */
+public interface ISysNoticeService
+{
+    /**
+     * 鏌ヨ鍏憡淇℃伅
+     * 
+     * @param noticeId 鍏憡ID
+     * @return 鍏憡淇℃伅
+     */
+    public SysNotice selectNoticeById(Long noticeId);
+
+    /**
+     * 鏌ヨ鍏憡鍒楄〃
+     * 
+     * @param notice 鍏憡淇℃伅
+     * @return 鍏憡闆嗗悎
+     */
+    public List<SysNotice> selectNoticeList(SysNotice notice);
+
+    /**
+     * 鏂板鍏憡
+     * 
+     * @param notice 鍏憡淇℃伅
+     * @return 缁撴灉
+     */
+    public int insertNotice(SysNotice notice);
+
+    /**
+     * 淇敼鍏憡
+     * 
+     * @param notice 鍏憡淇℃伅
+     * @return 缁撴灉
+     */
+    public int updateNotice(SysNotice notice);
+
+    /**
+     * 鍒犻櫎鍏憡淇℃伅
+     * 
+     * @param noticeId 鍏憡ID
+     * @return 缁撴灉
+     */
+    public int deleteNoticeById(Long noticeId);
+    
+    /**
+     * 鎵归噺鍒犻櫎鍏憡淇℃伅
+     * 
+     * @param noticeIds 闇�瑕佸垹闄ょ殑鍏憡ID
+     * @return 缁撴灉
+     */
+    public int deleteNoticeByIds(Long[] noticeIds);
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/service/ISysOperLogService.java b/jcdm-system/src/main/java/com/jcdm/system/service/ISysOperLogService.java
new file mode 100644
index 0000000..2843a29
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/service/ISysOperLogService.java
@@ -0,0 +1,48 @@
+package com.jcdm.system.service;
+
+import java.util.List;
+import com.jcdm.system.domain.SysOperLog;
+
+/**
+ * 鎿嶄綔鏃ュ織 鏈嶅姟灞�
+ * 
+ * @author jc
+ */
+public interface ISysOperLogService
+{
+    /**
+     * 鏂板鎿嶄綔鏃ュ織
+     * 
+     * @param operLog 鎿嶄綔鏃ュ織瀵硅薄
+     */
+    public void insertOperlog(SysOperLog operLog);
+
+    /**
+     * 鏌ヨ绯荤粺鎿嶄綔鏃ュ織闆嗗悎
+     * 
+     * @param operLog 鎿嶄綔鏃ュ織瀵硅薄
+     * @return 鎿嶄綔鏃ュ織闆嗗悎
+     */
+    public List<SysOperLog> selectOperLogList(SysOperLog operLog);
+
+    /**
+     * 鎵归噺鍒犻櫎绯荤粺鎿嶄綔鏃ュ織
+     * 
+     * @param operIds 闇�瑕佸垹闄ょ殑鎿嶄綔鏃ュ織ID
+     * @return 缁撴灉
+     */
+    public int deleteOperLogByIds(Long[] operIds);
+
+    /**
+     * 鏌ヨ鎿嶄綔鏃ュ織璇︾粏
+     * 
+     * @param operId 鎿嶄綔ID
+     * @return 鎿嶄綔鏃ュ織瀵硅薄
+     */
+    public SysOperLog selectOperLogById(Long operId);
+
+    /**
+     * 娓呯┖鎿嶄綔鏃ュ織
+     */
+    public void cleanOperLog();
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/service/ISysPostService.java b/jcdm-system/src/main/java/com/jcdm/system/service/ISysPostService.java
new file mode 100644
index 0000000..caee960
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/service/ISysPostService.java
@@ -0,0 +1,99 @@
+package com.jcdm.system.service;
+
+import java.util.List;
+import com.jcdm.system.domain.SysPost;
+
+/**
+ * 宀椾綅淇℃伅 鏈嶅姟灞�
+ * 
+ * @author jc
+ */
+public interface ISysPostService
+{
+    /**
+     * 鏌ヨ宀椾綅淇℃伅闆嗗悎
+     * 
+     * @param post 宀椾綅淇℃伅
+     * @return 宀椾綅鍒楄〃
+     */
+    public List<SysPost> selectPostList(SysPost post);
+
+    /**
+     * 鏌ヨ鎵�鏈夊矖浣�
+     * 
+     * @return 宀椾綅鍒楄〃
+     */
+    public List<SysPost> selectPostAll();
+
+    /**
+     * 閫氳繃宀椾綅ID鏌ヨ宀椾綅淇℃伅
+     * 
+     * @param postId 宀椾綅ID
+     * @return 瑙掕壊瀵硅薄淇℃伅
+     */
+    public SysPost selectPostById(Long postId);
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鑾峰彇宀椾綅閫夋嫨妗嗗垪琛�
+     * 
+     * @param userId 鐢ㄦ埛ID
+     * @return 閫変腑宀椾綅ID鍒楄〃
+     */
+    public List<Long> selectPostListByUserId(Long userId);
+
+    /**
+     * 鏍¢獙宀椾綅鍚嶇О
+     * 
+     * @param post 宀椾綅淇℃伅
+     * @return 缁撴灉
+     */
+    public boolean checkPostNameUnique(SysPost post);
+
+    /**
+     * 鏍¢獙宀椾綅缂栫爜
+     * 
+     * @param post 宀椾綅淇℃伅
+     * @return 缁撴灉
+     */
+    public boolean checkPostCodeUnique(SysPost post);
+
+    /**
+     * 閫氳繃宀椾綅ID鏌ヨ宀椾綅浣跨敤鏁伴噺
+     * 
+     * @param postId 宀椾綅ID
+     * @return 缁撴灉
+     */
+    public int countUserPostById(Long postId);
+
+    /**
+     * 鍒犻櫎宀椾綅淇℃伅
+     * 
+     * @param postId 宀椾綅ID
+     * @return 缁撴灉
+     */
+    public int deletePostById(Long postId);
+
+    /**
+     * 鎵归噺鍒犻櫎宀椾綅淇℃伅
+     * 
+     * @param postIds 闇�瑕佸垹闄ょ殑宀椾綅ID
+     * @return 缁撴灉
+     */
+    public int deletePostByIds(Long[] postIds);
+
+    /**
+     * 鏂板淇濆瓨宀椾綅淇℃伅
+     * 
+     * @param post 宀椾綅淇℃伅
+     * @return 缁撴灉
+     */
+    public int insertPost(SysPost post);
+
+    /**
+     * 淇敼淇濆瓨宀椾綅淇℃伅
+     * 
+     * @param post 宀椾綅淇℃伅
+     * @return 缁撴灉
+     */
+    public int updatePost(SysPost post);
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/service/ISysRoleService.java b/jcdm-system/src/main/java/com/jcdm/system/service/ISysRoleService.java
new file mode 100644
index 0000000..c2f87d4
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/service/ISysRoleService.java
@@ -0,0 +1,173 @@
+package com.jcdm.system.service;
+
+import java.util.List;
+import java.util.Set;
+import com.jcdm.common.core.domain.entity.SysRole;
+import com.jcdm.system.domain.SysUserRole;
+
+/**
+ * 瑙掕壊涓氬姟灞�
+ * 
+ * @author jc
+ */
+public interface ISysRoleService
+{
+    /**
+     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瑙掕壊鏁版嵁
+     * 
+     * @param role 瑙掕壊淇℃伅
+     * @return 瑙掕壊鏁版嵁闆嗗悎淇℃伅
+     */
+    public List<SysRole> selectRoleList(SysRole role);
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鏌ヨ瑙掕壊鍒楄〃
+     * 
+     * @param userId 鐢ㄦ埛ID
+     * @return 瑙掕壊鍒楄〃
+     */
+    public List<SysRole> selectRolesByUserId(Long userId);
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鏌ヨ瑙掕壊鏉冮檺
+     * 
+     * @param userId 鐢ㄦ埛ID
+     * @return 鏉冮檺鍒楄〃
+     */
+    public Set<String> selectRolePermissionByUserId(Long userId);
+
+    /**
+     * 鏌ヨ鎵�鏈夎鑹�
+     * 
+     * @return 瑙掕壊鍒楄〃
+     */
+    public List<SysRole> selectRoleAll();
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鑾峰彇瑙掕壊閫夋嫨妗嗗垪琛�
+     * 
+     * @param userId 鐢ㄦ埛ID
+     * @return 閫変腑瑙掕壊ID鍒楄〃
+     */
+    public List<Long> selectRoleListByUserId(Long userId);
+
+    /**
+     * 閫氳繃瑙掕壊ID鏌ヨ瑙掕壊
+     * 
+     * @param roleId 瑙掕壊ID
+     * @return 瑙掕壊瀵硅薄淇℃伅
+     */
+    public SysRole selectRoleById(Long roleId);
+
+    /**
+     * 鏍¢獙瑙掕壊鍚嶇О鏄惁鍞竴
+     * 
+     * @param role 瑙掕壊淇℃伅
+     * @return 缁撴灉
+     */
+    public boolean checkRoleNameUnique(SysRole role);
+
+    /**
+     * 鏍¢獙瑙掕壊鏉冮檺鏄惁鍞竴
+     * 
+     * @param role 瑙掕壊淇℃伅
+     * @return 缁撴灉
+     */
+    public boolean checkRoleKeyUnique(SysRole role);
+
+    /**
+     * 鏍¢獙瑙掕壊鏄惁鍏佽鎿嶄綔
+     * 
+     * @param role 瑙掕壊淇℃伅
+     */
+    public void checkRoleAllowed(SysRole role);
+
+    /**
+     * 鏍¢獙瑙掕壊鏄惁鏈夋暟鎹潈闄�
+     * 
+     * @param roleId 瑙掕壊id
+     */
+    public void checkRoleDataScope(Long roleId);
+
+    /**
+     * 閫氳繃瑙掕壊ID鏌ヨ瑙掕壊浣跨敤鏁伴噺
+     * 
+     * @param roleId 瑙掕壊ID
+     * @return 缁撴灉
+     */
+    public int countUserRoleByRoleId(Long roleId);
+
+    /**
+     * 鏂板淇濆瓨瑙掕壊淇℃伅
+     * 
+     * @param role 瑙掕壊淇℃伅
+     * @return 缁撴灉
+     */
+    public int insertRole(SysRole role);
+
+    /**
+     * 淇敼淇濆瓨瑙掕壊淇℃伅
+     * 
+     * @param role 瑙掕壊淇℃伅
+     * @return 缁撴灉
+     */
+    public int updateRole(SysRole role);
+
+    /**
+     * 淇敼瑙掕壊鐘舵��
+     * 
+     * @param role 瑙掕壊淇℃伅
+     * @return 缁撴灉
+     */
+    public int updateRoleStatus(SysRole role);
+
+    /**
+     * 淇敼鏁版嵁鏉冮檺淇℃伅
+     * 
+     * @param role 瑙掕壊淇℃伅
+     * @return 缁撴灉
+     */
+    public int authDataScope(SysRole role);
+
+    /**
+     * 閫氳繃瑙掕壊ID鍒犻櫎瑙掕壊
+     * 
+     * @param roleId 瑙掕壊ID
+     * @return 缁撴灉
+     */
+    public int deleteRoleById(Long roleId);
+
+    /**
+     * 鎵归噺鍒犻櫎瑙掕壊淇℃伅
+     * 
+     * @param roleIds 闇�瑕佸垹闄ょ殑瑙掕壊ID
+     * @return 缁撴灉
+     */
+    public int deleteRoleByIds(Long[] roleIds);
+
+    /**
+     * 鍙栨秷鎺堟潈鐢ㄦ埛瑙掕壊
+     * 
+     * @param userRole 鐢ㄦ埛鍜岃鑹插叧鑱斾俊鎭�
+     * @return 缁撴灉
+     */
+    public int deleteAuthUser(SysUserRole userRole);
+
+    /**
+     * 鎵归噺鍙栨秷鎺堟潈鐢ㄦ埛瑙掕壊
+     * 
+     * @param roleId 瑙掕壊ID
+     * @param userIds 闇�瑕佸彇娑堟巿鏉冪殑鐢ㄦ埛鏁版嵁ID
+     * @return 缁撴灉
+     */
+    public int deleteAuthUsers(Long roleId, Long[] userIds);
+
+    /**
+     * 鎵归噺閫夋嫨鎺堟潈鐢ㄦ埛瑙掕壊
+     * 
+     * @param roleId 瑙掕壊ID
+     * @param userIds 闇�瑕佸垹闄ょ殑鐢ㄦ埛鏁版嵁ID
+     * @return 缁撴灉
+     */
+    public int insertAuthUsers(Long roleId, Long[] userIds);
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/service/ISysUserOnlineService.java b/jcdm-system/src/main/java/com/jcdm/system/service/ISysUserOnlineService.java
new file mode 100644
index 0000000..38cce9a
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/service/ISysUserOnlineService.java
@@ -0,0 +1,48 @@
+package com.jcdm.system.service;
+
+import com.jcdm.common.core.domain.model.LoginUser;
+import com.jcdm.system.domain.SysUserOnline;
+
+/**
+ * 鍦ㄧ嚎鐢ㄦ埛 鏈嶅姟灞�
+ * 
+ * @author jc
+ */
+public interface ISysUserOnlineService
+{
+    /**
+     * 閫氳繃鐧诲綍鍦板潃鏌ヨ淇℃伅
+     * 
+     * @param ipaddr 鐧诲綍鍦板潃
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 鍦ㄧ嚎鐢ㄦ埛淇℃伅
+     */
+    public SysUserOnline selectOnlineByIpaddr(String ipaddr, LoginUser user);
+
+    /**
+     * 閫氳繃鐢ㄦ埛鍚嶇О鏌ヨ淇℃伅
+     * 
+     * @param userName 鐢ㄦ埛鍚嶇О
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 鍦ㄧ嚎鐢ㄦ埛淇℃伅
+     */
+    public SysUserOnline selectOnlineByUserName(String userName, LoginUser user);
+
+    /**
+     * 閫氳繃鐧诲綍鍦板潃/鐢ㄦ埛鍚嶇О鏌ヨ淇℃伅
+     * 
+     * @param ipaddr 鐧诲綍鍦板潃
+     * @param userName 鐢ㄦ埛鍚嶇О
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 鍦ㄧ嚎鐢ㄦ埛淇℃伅
+     */
+    public SysUserOnline selectOnlineByInfo(String ipaddr, String userName, LoginUser user);
+
+    /**
+     * 璁剧疆鍦ㄧ嚎鐢ㄦ埛淇℃伅
+     * 
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 鍦ㄧ嚎鐢ㄦ埛
+     */
+    public SysUserOnline loginUserToUserOnline(LoginUser user);
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/service/ISysUserService.java b/jcdm-system/src/main/java/com/jcdm/system/service/ISysUserService.java
new file mode 100644
index 0000000..7c7aad6
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/service/ISysUserService.java
@@ -0,0 +1,206 @@
+package com.jcdm.system.service;
+
+import java.util.List;
+import com.jcdm.common.core.domain.entity.SysUser;
+
+/**
+ * 鐢ㄦ埛 涓氬姟灞�
+ * 
+ * @author jc
+ */
+public interface ISysUserService
+{
+    /**
+     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ鐢ㄦ埛鍒楄〃
+     * 
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
+     */
+    public List<SysUser> selectUserList(SysUser user);
+
+    /**
+     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ宸插垎閰嶇敤鎴疯鑹插垪琛�
+     * 
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
+     */
+    public List<SysUser> selectAllocatedList(SysUser user);
+
+    /**
+     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ鏈垎閰嶇敤鎴疯鑹插垪琛�
+     * 
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
+     */
+    public List<SysUser> selectUnallocatedList(SysUser user);
+
+    /**
+     * 閫氳繃鐢ㄦ埛鍚嶆煡璇㈢敤鎴�
+     * 
+     * @param userName 鐢ㄦ埛鍚�
+     * @return 鐢ㄦ埛瀵硅薄淇℃伅
+     */
+    public SysUser selectUserByUserName(String userName);
+
+    /**
+     * 閫氳繃鐢ㄦ埛ID鏌ヨ鐢ㄦ埛
+     * 
+     * @param userId 鐢ㄦ埛ID
+     * @return 鐢ㄦ埛瀵硅薄淇℃伅
+     */
+    public SysUser selectUserById(Long userId);
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鏌ヨ鐢ㄦ埛鎵�灞炶鑹茬粍
+     * 
+     * @param userName 鐢ㄦ埛鍚�
+     * @return 缁撴灉
+     */
+    public String selectUserRoleGroup(String userName);
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鏌ヨ鐢ㄦ埛鎵�灞炲矖浣嶇粍
+     * 
+     * @param userName 鐢ㄦ埛鍚�
+     * @return 缁撴灉
+     */
+    public String selectUserPostGroup(String userName);
+
+    /**
+     * 鏍¢獙鐢ㄦ埛鍚嶇О鏄惁鍞竴
+     * 
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 缁撴灉
+     */
+    public boolean checkUserNameUnique(SysUser user);
+
+    /**
+     * 鏍¢獙鎵嬫満鍙风爜鏄惁鍞竴
+     *
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 缁撴灉
+     */
+    public boolean checkPhoneUnique(SysUser user);
+
+    /**
+     * 鏍¢獙email鏄惁鍞竴
+     *
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 缁撴灉
+     */
+    public boolean checkEmailUnique(SysUser user);
+
+    /**
+     * 鏍¢獙鐢ㄦ埛鏄惁鍏佽鎿嶄綔
+     * 
+     * @param user 鐢ㄦ埛淇℃伅
+     */
+    public void checkUserAllowed(SysUser user);
+
+    /**
+     * 鏍¢獙鐢ㄦ埛鏄惁鏈夋暟鎹潈闄�
+     * 
+     * @param userId 鐢ㄦ埛id
+     */
+    public void checkUserDataScope(Long userId);
+
+    /**
+     * 鏂板鐢ㄦ埛淇℃伅
+     * 
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 缁撴灉
+     */
+    public int insertUser(SysUser user);
+
+    /**
+     * 娉ㄥ唽鐢ㄦ埛淇℃伅
+     * 
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 缁撴灉
+     */
+    public boolean registerUser(SysUser user);
+
+    /**
+     * 淇敼鐢ㄦ埛淇℃伅
+     * 
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 缁撴灉
+     */
+    public int updateUser(SysUser user);
+
+    /**
+     * 鐢ㄦ埛鎺堟潈瑙掕壊
+     * 
+     * @param userId 鐢ㄦ埛ID
+     * @param roleIds 瑙掕壊缁�
+     */
+    public void insertUserAuth(Long userId, Long[] roleIds);
+
+    /**
+     * 淇敼鐢ㄦ埛鐘舵��
+     * 
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 缁撴灉
+     */
+    public int updateUserStatus(SysUser user);
+
+    /**
+     * 淇敼鐢ㄦ埛鍩烘湰淇℃伅
+     * 
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 缁撴灉
+     */
+    public int updateUserProfile(SysUser user);
+
+    /**
+     * 淇敼鐢ㄦ埛澶村儚
+     * 
+     * @param userName 鐢ㄦ埛鍚�
+     * @param avatar 澶村儚鍦板潃
+     * @return 缁撴灉
+     */
+    public boolean updateUserAvatar(String userName, String avatar);
+
+    /**
+     * 閲嶇疆鐢ㄦ埛瀵嗙爜
+     * 
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 缁撴灉
+     */
+    public int resetPwd(SysUser user);
+
+    /**
+     * 閲嶇疆鐢ㄦ埛瀵嗙爜
+     * 
+     * @param userName 鐢ㄦ埛鍚�
+     * @param password 瀵嗙爜
+     * @return 缁撴灉
+     */
+    public int resetUserPwd(String userName, String password);
+
+    /**
+     * 閫氳繃鐢ㄦ埛ID鍒犻櫎鐢ㄦ埛
+     * 
+     * @param userId 鐢ㄦ埛ID
+     * @return 缁撴灉
+     */
+    public int deleteUserById(Long userId);
+
+    /**
+     * 鎵归噺鍒犻櫎鐢ㄦ埛淇℃伅
+     * 
+     * @param userIds 闇�瑕佸垹闄ょ殑鐢ㄦ埛ID
+     * @return 缁撴灉
+     */
+    public int deleteUserByIds(Long[] userIds);
+
+    /**
+     * 瀵煎叆鐢ㄦ埛鏁版嵁
+     * 
+     * @param userList 鐢ㄦ埛鏁版嵁鍒楄〃
+     * @param isUpdateSupport 鏄惁鏇存柊鏀寔锛屽鏋滃凡瀛樺湪锛屽垯杩涜鏇存柊鏁版嵁
+     * @param operName 鎿嶄綔鐢ㄦ埛
+     * @return 缁撴灉
+     */
+    public String importUser(List<SysUser> userList, Boolean isUpdateSupport, String operName);
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysConfigServiceImpl.java b/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysConfigServiceImpl.java
new file mode 100644
index 0000000..6732bb0
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysConfigServiceImpl.java
@@ -0,0 +1,232 @@
+package com.jcdm.system.service.impl;
+
+import java.util.Collection;
+import java.util.List;
+import javax.annotation.PostConstruct;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.jcdm.common.annotation.DataSource;
+import com.jcdm.common.constant.CacheConstants;
+import com.jcdm.common.constant.UserConstants;
+import com.jcdm.common.core.redis.RedisCache;
+import com.jcdm.common.core.text.Convert;
+import com.jcdm.common.enums.DataSourceType;
+import com.jcdm.common.exception.ServiceException;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.system.domain.SysConfig;
+import com.jcdm.system.mapper.SysConfigMapper;
+import com.jcdm.system.service.ISysConfigService;
+
+/**
+ * 鍙傛暟閰嶇疆 鏈嶅姟灞傚疄鐜�
+ * 
+ * @author jc
+ */
+@Service
+public class SysConfigServiceImpl implements ISysConfigService
+{
+    @Autowired
+    private SysConfigMapper configMapper;
+
+    @Autowired
+    private RedisCache redisCache;
+
+    /**
+     * 椤圭洰鍚姩鏃讹紝鍒濆鍖栧弬鏁板埌缂撳瓨
+     */
+    @PostConstruct
+    public void init()
+    {
+        loadingConfigCache();
+    }
+
+    /**
+     * 鏌ヨ鍙傛暟閰嶇疆淇℃伅
+     * 
+     * @param configId 鍙傛暟閰嶇疆ID
+     * @return 鍙傛暟閰嶇疆淇℃伅
+     */
+    @Override
+    @DataSource(DataSourceType.MASTER)
+    public SysConfig selectConfigById(Long configId)
+    {
+        SysConfig config = new SysConfig();
+        config.setConfigId(configId);
+        return configMapper.selectConfig(config);
+    }
+
+    /**
+     * 鏍规嵁閿悕鏌ヨ鍙傛暟閰嶇疆淇℃伅
+     * 
+     * @param configKey 鍙傛暟key
+     * @return 鍙傛暟閿��
+     */
+    @Override
+    public String selectConfigByKey(String configKey)
+    {
+        String configValue = Convert.toStr(redisCache.getCacheObject(getCacheKey(configKey)));
+        if (StringUtils.isNotEmpty(configValue))
+        {
+            return configValue;
+        }
+        SysConfig config = new SysConfig();
+        config.setConfigKey(configKey);
+        SysConfig retConfig = configMapper.selectConfig(config);
+        if (StringUtils.isNotNull(retConfig))
+        {
+            redisCache.setCacheObject(getCacheKey(configKey), retConfig.getConfigValue());
+            return retConfig.getConfigValue();
+        }
+        return StringUtils.EMPTY;
+    }
+
+    /**
+     * 鑾峰彇楠岃瘉鐮佸紑鍏�
+     * 
+     * @return true寮�鍚紝false鍏抽棴
+     */
+    @Override
+    public boolean selectCaptchaEnabled()
+    {
+        String captchaEnabled = selectConfigByKey("sys.account.captchaEnabled");
+        if (StringUtils.isEmpty(captchaEnabled))
+        {
+            return true;
+        }
+        return Convert.toBool(captchaEnabled);
+    }
+
+    /**
+     * 鏌ヨ鍙傛暟閰嶇疆鍒楄〃
+     * 
+     * @param config 鍙傛暟閰嶇疆淇℃伅
+     * @return 鍙傛暟閰嶇疆闆嗗悎
+     */
+    @Override
+    public List<SysConfig> selectConfigList(SysConfig config)
+    {
+        return configMapper.selectConfigList(config);
+    }
+
+    /**
+     * 鏂板鍙傛暟閰嶇疆
+     * 
+     * @param config 鍙傛暟閰嶇疆淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertConfig(SysConfig config)
+    {
+        int row = configMapper.insertConfig(config);
+        if (row > 0)
+        {
+            redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
+        }
+        return row;
+    }
+
+    /**
+     * 淇敼鍙傛暟閰嶇疆
+     * 
+     * @param config 鍙傛暟閰嶇疆淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateConfig(SysConfig config)
+    {
+        SysConfig temp = configMapper.selectConfigById(config.getConfigId());
+        if (!StringUtils.equals(temp.getConfigKey(), config.getConfigKey()))
+        {
+            redisCache.deleteObject(getCacheKey(temp.getConfigKey()));
+        }
+
+        int row = configMapper.updateConfig(config);
+        if (row > 0)
+        {
+            redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
+        }
+        return row;
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎鍙傛暟淇℃伅
+     * 
+     * @param configIds 闇�瑕佸垹闄ょ殑鍙傛暟ID
+     */
+    @Override
+    public void deleteConfigByIds(Long[] configIds)
+    {
+        for (Long configId : configIds)
+        {
+            SysConfig config = selectConfigById(configId);
+            if (StringUtils.equals(UserConstants.YES, config.getConfigType()))
+            {
+                throw new ServiceException(String.format("鍐呯疆鍙傛暟銆�%1$s銆戜笉鑳藉垹闄� ", config.getConfigKey()));
+            }
+            configMapper.deleteConfigById(configId);
+            redisCache.deleteObject(getCacheKey(config.getConfigKey()));
+        }
+    }
+
+    /**
+     * 鍔犺浇鍙傛暟缂撳瓨鏁版嵁
+     */
+    @Override
+    public void loadingConfigCache()
+    {
+        List<SysConfig> configsList = configMapper.selectConfigList(new SysConfig());
+        for (SysConfig config : configsList)
+        {
+            redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
+        }
+    }
+
+    /**
+     * 娓呯┖鍙傛暟缂撳瓨鏁版嵁
+     */
+    @Override
+    public void clearConfigCache()
+    {
+        Collection<String> keys = redisCache.keys(CacheConstants.SYS_CONFIG_KEY + "*");
+        redisCache.deleteObject(keys);
+    }
+
+    /**
+     * 閲嶇疆鍙傛暟缂撳瓨鏁版嵁
+     */
+    @Override
+    public void resetConfigCache()
+    {
+        clearConfigCache();
+        loadingConfigCache();
+    }
+
+    /**
+     * 鏍¢獙鍙傛暟閿悕鏄惁鍞竴
+     * 
+     * @param config 鍙傛暟閰嶇疆淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public boolean checkConfigKeyUnique(SysConfig config)
+    {
+        Long configId = StringUtils.isNull(config.getConfigId()) ? -1L : config.getConfigId();
+        SysConfig info = configMapper.checkConfigKeyUnique(config.getConfigKey());
+        if (StringUtils.isNotNull(info) && info.getConfigId().longValue() != configId.longValue())
+        {
+            return UserConstants.NOT_UNIQUE;
+        }
+        return UserConstants.UNIQUE;
+    }
+
+    /**
+     * 璁剧疆cache key
+     * 
+     * @param configKey 鍙傛暟閿�
+     * @return 缂撳瓨閿甼ey
+     */
+    private String getCacheKey(String configKey)
+    {
+        return CacheConstants.SYS_CONFIG_KEY + configKey;
+    }
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysDeptServiceImpl.java b/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysDeptServiceImpl.java
new file mode 100644
index 0000000..6378317
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysDeptServiceImpl.java
@@ -0,0 +1,338 @@
+package com.jcdm.system.service.impl;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.jcdm.common.annotation.DataScope;
+import com.jcdm.common.constant.UserConstants;
+import com.jcdm.common.core.domain.TreeSelect;
+import com.jcdm.common.core.domain.entity.SysDept;
+import com.jcdm.common.core.domain.entity.SysRole;
+import com.jcdm.common.core.domain.entity.SysUser;
+import com.jcdm.common.core.text.Convert;
+import com.jcdm.common.exception.ServiceException;
+import com.jcdm.common.utils.SecurityUtils;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.common.utils.spring.SpringUtils;
+import com.jcdm.system.mapper.SysDeptMapper;
+import com.jcdm.system.mapper.SysRoleMapper;
+import com.jcdm.system.service.ISysDeptService;
+
+/**
+ * 閮ㄩ棬绠$悊 鏈嶅姟瀹炵幇
+ * 
+ * @author jc
+ */
+@Service
+public class SysDeptServiceImpl implements ISysDeptService
+{
+    @Autowired
+    private SysDeptMapper deptMapper;
+
+    @Autowired
+    private SysRoleMapper roleMapper;
+
+    /**
+     * 鏌ヨ閮ㄩ棬绠$悊鏁版嵁
+     * 
+     * @param dept 閮ㄩ棬淇℃伅
+     * @return 閮ㄩ棬淇℃伅闆嗗悎
+     */
+    @Override
+    @DataScope(deptAlias = "d")
+    public List<SysDept> selectDeptList(SysDept dept)
+    {
+        return deptMapper.selectDeptList(dept);
+    }
+
+    /**
+     * 鏌ヨ閮ㄩ棬鏍戠粨鏋勪俊鎭�
+     * 
+     * @param dept 閮ㄩ棬淇℃伅
+     * @return 閮ㄩ棬鏍戜俊鎭泦鍚�
+     */
+    @Override
+    public List<TreeSelect> selectDeptTreeList(SysDept dept)
+    {
+        List<SysDept> depts = SpringUtils.getAopProxy(this).selectDeptList(dept);
+        return buildDeptTreeSelect(depts);
+    }
+
+    /**
+     * 鏋勫缓鍓嶇鎵�闇�瑕佹爲缁撴瀯
+     * 
+     * @param depts 閮ㄩ棬鍒楄〃
+     * @return 鏍戠粨鏋勫垪琛�
+     */
+    @Override
+    public List<SysDept> buildDeptTree(List<SysDept> depts)
+    {
+        List<SysDept> returnList = new ArrayList<SysDept>();
+        List<Long> tempList = depts.stream().map(SysDept::getDeptId).collect(Collectors.toList());
+        for (SysDept dept : depts)
+        {
+            // 濡傛灉鏄《绾ц妭鐐�, 閬嶅巻璇ョ埗鑺傜偣鐨勬墍鏈夊瓙鑺傜偣
+            if (!tempList.contains(dept.getParentId()))
+            {
+                recursionFn(depts, dept);
+                returnList.add(dept);
+            }
+        }
+        if (returnList.isEmpty())
+        {
+            returnList = depts;
+        }
+        return returnList;
+    }
+
+    /**
+     * 鏋勫缓鍓嶇鎵�闇�瑕佷笅鎷夋爲缁撴瀯
+     * 
+     * @param depts 閮ㄩ棬鍒楄〃
+     * @return 涓嬫媺鏍戠粨鏋勫垪琛�
+     */
+    @Override
+    public List<TreeSelect> buildDeptTreeSelect(List<SysDept> depts)
+    {
+        List<SysDept> deptTrees = buildDeptTree(depts);
+        return deptTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
+    }
+
+    /**
+     * 鏍规嵁瑙掕壊ID鏌ヨ閮ㄩ棬鏍戜俊鎭�
+     * 
+     * @param roleId 瑙掕壊ID
+     * @return 閫変腑閮ㄩ棬鍒楄〃
+     */
+    @Override
+    public List<Long> selectDeptListByRoleId(Long roleId)
+    {
+        SysRole role = roleMapper.selectRoleById(roleId);
+        return deptMapper.selectDeptListByRoleId(roleId, role.isDeptCheckStrictly());
+    }
+
+    /**
+     * 鏍规嵁閮ㄩ棬ID鏌ヨ淇℃伅
+     * 
+     * @param deptId 閮ㄩ棬ID
+     * @return 閮ㄩ棬淇℃伅
+     */
+    @Override
+    public SysDept selectDeptById(Long deptId)
+    {
+        return deptMapper.selectDeptById(deptId);
+    }
+
+    /**
+     * 鏍规嵁ID鏌ヨ鎵�鏈夊瓙閮ㄩ棬锛堟甯哥姸鎬侊級
+     * 
+     * @param deptId 閮ㄩ棬ID
+     * @return 瀛愰儴闂ㄦ暟
+     */
+    @Override
+    public int selectNormalChildrenDeptById(Long deptId)
+    {
+        return deptMapper.selectNormalChildrenDeptById(deptId);
+    }
+
+    /**
+     * 鏄惁瀛樺湪瀛愯妭鐐�
+     * 
+     * @param deptId 閮ㄩ棬ID
+     * @return 缁撴灉
+     */
+    @Override
+    public boolean hasChildByDeptId(Long deptId)
+    {
+        int result = deptMapper.hasChildByDeptId(deptId);
+        return result > 0;
+    }
+
+    /**
+     * 鏌ヨ閮ㄩ棬鏄惁瀛樺湪鐢ㄦ埛
+     * 
+     * @param deptId 閮ㄩ棬ID
+     * @return 缁撴灉 true 瀛樺湪 false 涓嶅瓨鍦�
+     */
+    @Override
+    public boolean checkDeptExistUser(Long deptId)
+    {
+        int result = deptMapper.checkDeptExistUser(deptId);
+        return result > 0;
+    }
+
+    /**
+     * 鏍¢獙閮ㄩ棬鍚嶇О鏄惁鍞竴
+     * 
+     * @param dept 閮ㄩ棬淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public boolean checkDeptNameUnique(SysDept dept)
+    {
+        Long deptId = StringUtils.isNull(dept.getDeptId()) ? -1L : dept.getDeptId();
+        SysDept info = deptMapper.checkDeptNameUnique(dept.getDeptName(), dept.getParentId());
+        if (StringUtils.isNotNull(info) && info.getDeptId().longValue() != deptId.longValue())
+        {
+            return UserConstants.NOT_UNIQUE;
+        }
+        return UserConstants.UNIQUE;
+    }
+
+    /**
+     * 鏍¢獙閮ㄩ棬鏄惁鏈夋暟鎹潈闄�
+     * 
+     * @param deptId 閮ㄩ棬id
+     */
+    @Override
+    public void checkDeptDataScope(Long deptId)
+    {
+        if (!SysUser.isAdmin(SecurityUtils.getUserId()))
+        {
+            SysDept dept = new SysDept();
+            dept.setDeptId(deptId);
+            List<SysDept> depts = SpringUtils.getAopProxy(this).selectDeptList(dept);
+            if (StringUtils.isEmpty(depts))
+            {
+                throw new ServiceException("娌℃湁鏉冮檺璁块棶閮ㄩ棬鏁版嵁锛�");
+            }
+        }
+    }
+
+    /**
+     * 鏂板淇濆瓨閮ㄩ棬淇℃伅
+     * 
+     * @param dept 閮ㄩ棬淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertDept(SysDept dept)
+    {
+        SysDept info = deptMapper.selectDeptById(dept.getParentId());
+        // 濡傛灉鐖惰妭鐐逛笉涓烘甯哥姸鎬�,鍒欎笉鍏佽鏂板瀛愯妭鐐�
+        if (!UserConstants.DEPT_NORMAL.equals(info.getStatus()))
+        {
+            throw new ServiceException("閮ㄩ棬鍋滅敤锛屼笉鍏佽鏂板");
+        }
+        dept.setAncestors(info.getAncestors() + "," + dept.getParentId());
+        return deptMapper.insertDept(dept);
+    }
+
+    /**
+     * 淇敼淇濆瓨閮ㄩ棬淇℃伅
+     * 
+     * @param dept 閮ㄩ棬淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateDept(SysDept dept)
+    {
+        SysDept newParentDept = deptMapper.selectDeptById(dept.getParentId());
+        SysDept oldDept = deptMapper.selectDeptById(dept.getDeptId());
+        if (StringUtils.isNotNull(newParentDept) && StringUtils.isNotNull(oldDept))
+        {
+            String newAncestors = newParentDept.getAncestors() + "," + newParentDept.getDeptId();
+            String oldAncestors = oldDept.getAncestors();
+            dept.setAncestors(newAncestors);
+            updateDeptChildren(dept.getDeptId(), newAncestors, oldAncestors);
+        }
+        int result = deptMapper.updateDept(dept);
+        if (UserConstants.DEPT_NORMAL.equals(dept.getStatus()) && StringUtils.isNotEmpty(dept.getAncestors())
+                && !StringUtils.equals("0", dept.getAncestors()))
+        {
+            // 濡傛灉璇ラ儴闂ㄦ槸鍚敤鐘舵�侊紝鍒欏惎鐢ㄨ閮ㄩ棬鐨勬墍鏈変笂绾ч儴闂�
+            updateParentDeptStatusNormal(dept);
+        }
+        return result;
+    }
+
+    /**
+     * 淇敼璇ラ儴闂ㄧ殑鐖剁骇閮ㄩ棬鐘舵��
+     * 
+     * @param dept 褰撳墠閮ㄩ棬
+     */
+    private void updateParentDeptStatusNormal(SysDept dept)
+    {
+        String ancestors = dept.getAncestors();
+        Long[] deptIds = Convert.toLongArray(ancestors);
+        deptMapper.updateDeptStatusNormal(deptIds);
+    }
+
+    /**
+     * 淇敼瀛愬厓绱犲叧绯�
+     * 
+     * @param deptId 琚慨鏀圭殑閮ㄩ棬ID
+     * @param newAncestors 鏂扮殑鐖禝D闆嗗悎
+     * @param oldAncestors 鏃х殑鐖禝D闆嗗悎
+     */
+    public void updateDeptChildren(Long deptId, String newAncestors, String oldAncestors)
+    {
+        List<SysDept> children = deptMapper.selectChildrenDeptById(deptId);
+        for (SysDept child : children)
+        {
+            child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors));
+        }
+        if (children.size() > 0)
+        {
+            deptMapper.updateDeptChildren(children);
+        }
+    }
+
+    /**
+     * 鍒犻櫎閮ㄩ棬绠$悊淇℃伅
+     * 
+     * @param deptId 閮ㄩ棬ID
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteDeptById(Long deptId)
+    {
+        return deptMapper.deleteDeptById(deptId);
+    }
+
+    /**
+     * 閫掑綊鍒楄〃
+     */
+    private void recursionFn(List<SysDept> list, SysDept t)
+    {
+        // 寰楀埌瀛愯妭鐐瑰垪琛�
+        List<SysDept> childList = getChildList(list, t);
+        t.setChildren(childList);
+        for (SysDept tChild : childList)
+        {
+            if (hasChild(list, tChild))
+            {
+                recursionFn(list, tChild);
+            }
+        }
+    }
+
+    /**
+     * 寰楀埌瀛愯妭鐐瑰垪琛�
+     */
+    private List<SysDept> getChildList(List<SysDept> list, SysDept t)
+    {
+        List<SysDept> tlist = new ArrayList<SysDept>();
+        Iterator<SysDept> it = list.iterator();
+        while (it.hasNext())
+        {
+            SysDept n = (SysDept) it.next();
+            if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().longValue() == t.getDeptId().longValue())
+            {
+                tlist.add(n);
+            }
+        }
+        return tlist;
+    }
+
+    /**
+     * 鍒ゆ柇鏄惁鏈夊瓙鑺傜偣
+     */
+    private boolean hasChild(List<SysDept> list, SysDept t)
+    {
+        return getChildList(list, t).size() > 0;
+    }
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysDictDataServiceImpl.java b/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysDictDataServiceImpl.java
new file mode 100644
index 0000000..834f9f4
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysDictDataServiceImpl.java
@@ -0,0 +1,111 @@
+package com.jcdm.system.service.impl;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.jcdm.common.core.domain.entity.SysDictData;
+import com.jcdm.common.utils.DictUtils;
+import com.jcdm.system.mapper.SysDictDataMapper;
+import com.jcdm.system.service.ISysDictDataService;
+
+/**
+ * 瀛楀吀 涓氬姟灞傚鐞�
+ * 
+ * @author jc
+ */
+@Service
+public class SysDictDataServiceImpl implements ISysDictDataService
+{
+    @Autowired
+    private SysDictDataMapper dictDataMapper;
+
+    /**
+     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瀛楀吀鏁版嵁
+     * 
+     * @param dictData 瀛楀吀鏁版嵁淇℃伅
+     * @return 瀛楀吀鏁版嵁闆嗗悎淇℃伅
+     */
+    @Override
+    public List<SysDictData> selectDictDataList(SysDictData dictData)
+    {
+        return dictDataMapper.selectDictDataList(dictData);
+    }
+
+    /**
+     * 鏍规嵁瀛楀吀绫诲瀷鍜屽瓧鍏搁敭鍊兼煡璇㈠瓧鍏告暟鎹俊鎭�
+     * 
+     * @param dictType 瀛楀吀绫诲瀷
+     * @param dictValue 瀛楀吀閿��
+     * @return 瀛楀吀鏍囩
+     */
+    @Override
+    public String selectDictLabel(String dictType, String dictValue)
+    {
+        return dictDataMapper.selectDictLabel(dictType, dictValue);
+    }
+
+    /**
+     * 鏍规嵁瀛楀吀鏁版嵁ID鏌ヨ淇℃伅
+     * 
+     * @param dictCode 瀛楀吀鏁版嵁ID
+     * @return 瀛楀吀鏁版嵁
+     */
+    @Override
+    public SysDictData selectDictDataById(Long dictCode)
+    {
+        return dictDataMapper.selectDictDataById(dictCode);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎瀛楀吀鏁版嵁淇℃伅
+     * 
+     * @param dictCodes 闇�瑕佸垹闄ょ殑瀛楀吀鏁版嵁ID
+     */
+    @Override
+    public void deleteDictDataByIds(Long[] dictCodes)
+    {
+        for (Long dictCode : dictCodes)
+        {
+            SysDictData data = selectDictDataById(dictCode);
+            dictDataMapper.deleteDictDataById(dictCode);
+            List<SysDictData> dictDatas = dictDataMapper.selectDictDataByType(data.getDictType());
+            DictUtils.setDictCache(data.getDictType(), dictDatas);
+        }
+    }
+
+    /**
+     * 鏂板淇濆瓨瀛楀吀鏁版嵁淇℃伅
+     * 
+     * @param data 瀛楀吀鏁版嵁淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertDictData(SysDictData data)
+    {
+        int row = dictDataMapper.insertDictData(data);
+        if (row > 0)
+        {
+            List<SysDictData> dictDatas = dictDataMapper.selectDictDataByType(data.getDictType());
+            DictUtils.setDictCache(data.getDictType(), dictDatas);
+        }
+        return row;
+    }
+
+    /**
+     * 淇敼淇濆瓨瀛楀吀鏁版嵁淇℃伅
+     * 
+     * @param data 瀛楀吀鏁版嵁淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateDictData(SysDictData data)
+    {
+        int row = dictDataMapper.updateDictData(data);
+        if (row > 0)
+        {
+            List<SysDictData> dictDatas = dictDataMapper.selectDictDataByType(data.getDictType());
+            DictUtils.setDictCache(data.getDictType(), dictDatas);
+        }
+        return row;
+    }
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysDictTypeServiceImpl.java b/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysDictTypeServiceImpl.java
new file mode 100644
index 0000000..0381cbb
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysDictTypeServiceImpl.java
@@ -0,0 +1,223 @@
+package com.jcdm.system.service.impl;
+
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import javax.annotation.PostConstruct;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import com.jcdm.common.constant.UserConstants;
+import com.jcdm.common.core.domain.entity.SysDictData;
+import com.jcdm.common.core.domain.entity.SysDictType;
+import com.jcdm.common.exception.ServiceException;
+import com.jcdm.common.utils.DictUtils;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.system.mapper.SysDictDataMapper;
+import com.jcdm.system.mapper.SysDictTypeMapper;
+import com.jcdm.system.service.ISysDictTypeService;
+
+/**
+ * 瀛楀吀 涓氬姟灞傚鐞�
+ * 
+ * @author jc
+ */
+@Service
+public class SysDictTypeServiceImpl implements ISysDictTypeService
+{
+    @Autowired
+    private SysDictTypeMapper dictTypeMapper;
+
+    @Autowired
+    private SysDictDataMapper dictDataMapper;
+
+    /**
+     * 椤圭洰鍚姩鏃讹紝鍒濆鍖栧瓧鍏稿埌缂撳瓨
+     */
+    @PostConstruct
+    public void init()
+    {
+        loadingDictCache();
+    }
+
+    /**
+     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瀛楀吀绫诲瀷
+     * 
+     * @param dictType 瀛楀吀绫诲瀷淇℃伅
+     * @return 瀛楀吀绫诲瀷闆嗗悎淇℃伅
+     */
+    @Override
+    public List<SysDictType> selectDictTypeList(SysDictType dictType)
+    {
+        return dictTypeMapper.selectDictTypeList(dictType);
+    }
+
+    /**
+     * 鏍规嵁鎵�鏈夊瓧鍏哥被鍨�
+     * 
+     * @return 瀛楀吀绫诲瀷闆嗗悎淇℃伅
+     */
+    @Override
+    public List<SysDictType> selectDictTypeAll()
+    {
+        return dictTypeMapper.selectDictTypeAll();
+    }
+
+    /**
+     * 鏍规嵁瀛楀吀绫诲瀷鏌ヨ瀛楀吀鏁版嵁
+     * 
+     * @param dictType 瀛楀吀绫诲瀷
+     * @return 瀛楀吀鏁版嵁闆嗗悎淇℃伅
+     */
+    @Override
+    public List<SysDictData> selectDictDataByType(String dictType)
+    {
+        List<SysDictData> dictDatas = DictUtils.getDictCache(dictType);
+        if (StringUtils.isNotEmpty(dictDatas))
+        {
+            return dictDatas;
+        }
+        dictDatas = dictDataMapper.selectDictDataByType(dictType);
+        if (StringUtils.isNotEmpty(dictDatas))
+        {
+            DictUtils.setDictCache(dictType, dictDatas);
+            return dictDatas;
+        }
+        return null;
+    }
+
+    /**
+     * 鏍规嵁瀛楀吀绫诲瀷ID鏌ヨ淇℃伅
+     * 
+     * @param dictId 瀛楀吀绫诲瀷ID
+     * @return 瀛楀吀绫诲瀷
+     */
+    @Override
+    public SysDictType selectDictTypeById(Long dictId)
+    {
+        return dictTypeMapper.selectDictTypeById(dictId);
+    }
+
+    /**
+     * 鏍规嵁瀛楀吀绫诲瀷鏌ヨ淇℃伅
+     * 
+     * @param dictType 瀛楀吀绫诲瀷
+     * @return 瀛楀吀绫诲瀷
+     */
+    @Override
+    public SysDictType selectDictTypeByType(String dictType)
+    {
+        return dictTypeMapper.selectDictTypeByType(dictType);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎瀛楀吀绫诲瀷淇℃伅
+     * 
+     * @param dictIds 闇�瑕佸垹闄ょ殑瀛楀吀ID
+     */
+    @Override
+    public void deleteDictTypeByIds(Long[] dictIds)
+    {
+        for (Long dictId : dictIds)
+        {
+            SysDictType dictType = selectDictTypeById(dictId);
+            if (dictDataMapper.countDictDataByType(dictType.getDictType()) > 0)
+            {
+                throw new ServiceException(String.format("%1$s宸插垎閰�,涓嶈兘鍒犻櫎", dictType.getDictName()));
+            }
+            dictTypeMapper.deleteDictTypeById(dictId);
+            DictUtils.removeDictCache(dictType.getDictType());
+        }
+    }
+
+    /**
+     * 鍔犺浇瀛楀吀缂撳瓨鏁版嵁
+     */
+    @Override
+    public void loadingDictCache()
+    {
+        SysDictData dictData = new SysDictData();
+        dictData.setStatus("0");
+        Map<String, List<SysDictData>> dictDataMap = dictDataMapper.selectDictDataList(dictData).stream().collect(Collectors.groupingBy(SysDictData::getDictType));
+        for (Map.Entry<String, List<SysDictData>> entry : dictDataMap.entrySet())
+        {
+            DictUtils.setDictCache(entry.getKey(), entry.getValue().stream().sorted(Comparator.comparing(SysDictData::getDictSort)).collect(Collectors.toList()));
+        }
+    }
+
+    /**
+     * 娓呯┖瀛楀吀缂撳瓨鏁版嵁
+     */
+    @Override
+    public void clearDictCache()
+    {
+        DictUtils.clearDictCache();
+    }
+
+    /**
+     * 閲嶇疆瀛楀吀缂撳瓨鏁版嵁
+     */
+    @Override
+    public void resetDictCache()
+    {
+        clearDictCache();
+        loadingDictCache();
+    }
+
+    /**
+     * 鏂板淇濆瓨瀛楀吀绫诲瀷淇℃伅
+     * 
+     * @param dict 瀛楀吀绫诲瀷淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertDictType(SysDictType dict)
+    {
+        int row = dictTypeMapper.insertDictType(dict);
+        if (row > 0)
+        {
+            DictUtils.setDictCache(dict.getDictType(), null);
+        }
+        return row;
+    }
+
+    /**
+     * 淇敼淇濆瓨瀛楀吀绫诲瀷淇℃伅
+     * 
+     * @param dict 瀛楀吀绫诲瀷淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    @Transactional
+    public int updateDictType(SysDictType dict)
+    {
+        SysDictType oldDict = dictTypeMapper.selectDictTypeById(dict.getDictId());
+        dictDataMapper.updateDictDataType(oldDict.getDictType(), dict.getDictType());
+        int row = dictTypeMapper.updateDictType(dict);
+        if (row > 0)
+        {
+            List<SysDictData> dictDatas = dictDataMapper.selectDictDataByType(dict.getDictType());
+            DictUtils.setDictCache(dict.getDictType(), dictDatas);
+        }
+        return row;
+    }
+
+    /**
+     * 鏍¢獙瀛楀吀绫诲瀷绉版槸鍚﹀敮涓�
+     * 
+     * @param dict 瀛楀吀绫诲瀷
+     * @return 缁撴灉
+     */
+    @Override
+    public boolean checkDictTypeUnique(SysDictType dict)
+    {
+        Long dictId = StringUtils.isNull(dict.getDictId()) ? -1L : dict.getDictId();
+        SysDictType dictType = dictTypeMapper.checkDictTypeUnique(dict.getDictType());
+        if (StringUtils.isNotNull(dictType) && dictType.getDictId().longValue() != dictId.longValue())
+        {
+            return UserConstants.NOT_UNIQUE;
+        }
+        return UserConstants.UNIQUE;
+    }
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysLogininforServiceImpl.java b/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysLogininforServiceImpl.java
new file mode 100644
index 0000000..443188f
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysLogininforServiceImpl.java
@@ -0,0 +1,65 @@
+package com.jcdm.system.service.impl;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.jcdm.system.domain.SysLogininfor;
+import com.jcdm.system.mapper.SysLogininforMapper;
+import com.jcdm.system.service.ISysLogininforService;
+
+/**
+ * 绯荤粺璁块棶鏃ュ織鎯呭喌淇℃伅 鏈嶅姟灞傚鐞�
+ * 
+ * @author jc
+ */
+@Service
+public class SysLogininforServiceImpl implements ISysLogininforService
+{
+
+    @Autowired
+    private SysLogininforMapper logininforMapper;
+
+    /**
+     * 鏂板绯荤粺鐧诲綍鏃ュ織
+     * 
+     * @param logininfor 璁块棶鏃ュ織瀵硅薄
+     */
+    @Override
+    public void insertLogininfor(SysLogininfor logininfor)
+    {
+        logininforMapper.insertLogininfor(logininfor);
+    }
+
+    /**
+     * 鏌ヨ绯荤粺鐧诲綍鏃ュ織闆嗗悎
+     * 
+     * @param logininfor 璁块棶鏃ュ織瀵硅薄
+     * @return 鐧诲綍璁板綍闆嗗悎
+     */
+    @Override
+    public List<SysLogininfor> selectLogininforList(SysLogininfor logininfor)
+    {
+        return logininforMapper.selectLogininforList(logininfor);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎绯荤粺鐧诲綍鏃ュ織
+     * 
+     * @param infoIds 闇�瑕佸垹闄ょ殑鐧诲綍鏃ュ織ID
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteLogininforByIds(Long[] infoIds)
+    {
+        return logininforMapper.deleteLogininforByIds(infoIds);
+    }
+
+    /**
+     * 娓呯┖绯荤粺鐧诲綍鏃ュ織
+     */
+    @Override
+    public void cleanLogininfor()
+    {
+        logininforMapper.cleanLogininfor();
+    }
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysMenuServiceImpl.java b/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysMenuServiceImpl.java
new file mode 100644
index 0000000..f535fc0
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysMenuServiceImpl.java
@@ -0,0 +1,531 @@
+package com.jcdm.system.service.impl;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.jcdm.common.constant.Constants;
+import com.jcdm.common.constant.UserConstants;
+import com.jcdm.common.core.domain.TreeSelect;
+import com.jcdm.common.core.domain.entity.SysMenu;
+import com.jcdm.common.core.domain.entity.SysRole;
+import com.jcdm.common.core.domain.entity.SysUser;
+import com.jcdm.common.utils.SecurityUtils;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.system.domain.vo.MetaVo;
+import com.jcdm.system.domain.vo.RouterVo;
+import com.jcdm.system.mapper.SysMenuMapper;
+import com.jcdm.system.mapper.SysRoleMapper;
+import com.jcdm.system.mapper.SysRoleMenuMapper;
+import com.jcdm.system.service.ISysMenuService;
+
+/**
+ * 鑿滃崟 涓氬姟灞傚鐞�
+ * 
+ * @author jc
+ */
+@Service
+public class SysMenuServiceImpl implements ISysMenuService
+{
+    public static final String PREMISSION_STRING = "perms[\"{0}\"]";
+
+    @Autowired
+    private SysMenuMapper menuMapper;
+
+    @Autowired
+    private SysRoleMapper roleMapper;
+
+    @Autowired
+    private SysRoleMenuMapper roleMenuMapper;
+
+    /**
+     * 鏍规嵁鐢ㄦ埛鏌ヨ绯荤粺鑿滃崟鍒楄〃
+     * 
+     * @param userId 鐢ㄦ埛ID
+     * @return 鑿滃崟鍒楄〃
+     */
+    @Override
+    public List<SysMenu> selectMenuList(Long userId)
+    {
+        return selectMenuList(new SysMenu(), userId);
+    }
+
+    /**
+     * 鏌ヨ绯荤粺鑿滃崟鍒楄〃
+     * 
+     * @param menu 鑿滃崟淇℃伅
+     * @return 鑿滃崟鍒楄〃
+     */
+    @Override
+    public List<SysMenu> selectMenuList(SysMenu menu, Long userId)
+    {
+        List<SysMenu> menuList = null;
+        // 绠$悊鍛樻樉绀烘墍鏈夎彍鍗曚俊鎭�
+        if (SysUser.isAdmin(userId))
+        {
+            menuList = menuMapper.selectMenuList(menu);
+        }
+        else
+        {
+            menu.getParams().put("userId", userId);
+            menuList = menuMapper.selectMenuListByUserId(menu);
+        }
+        return menuList;
+    }
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鏌ヨ鏉冮檺
+     * 
+     * @param userId 鐢ㄦ埛ID
+     * @return 鏉冮檺鍒楄〃
+     */
+    @Override
+    public Set<String> selectMenuPermsByUserId(Long userId)
+    {
+        List<String> perms = menuMapper.selectMenuPermsByUserId(userId);
+        Set<String> permsSet = new HashSet<>();
+        for (String perm : perms)
+        {
+            if (StringUtils.isNotEmpty(perm))
+            {
+                permsSet.addAll(Arrays.asList(perm.trim().split(",")));
+            }
+        }
+        return permsSet;
+    }
+
+    /**
+     * 鏍规嵁瑙掕壊ID鏌ヨ鏉冮檺
+     * 
+     * @param roleId 瑙掕壊ID
+     * @return 鏉冮檺鍒楄〃
+     */
+    @Override
+    public Set<String> selectMenuPermsByRoleId(Long roleId)
+    {
+        List<String> perms = menuMapper.selectMenuPermsByRoleId(roleId);
+        Set<String> permsSet = new HashSet<>();
+        for (String perm : perms)
+        {
+            if (StringUtils.isNotEmpty(perm))
+            {
+                permsSet.addAll(Arrays.asList(perm.trim().split(",")));
+            }
+        }
+        return permsSet;
+    }
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鏌ヨ鑿滃崟
+     * 
+     * @param userId 鐢ㄦ埛鍚嶇О
+     * @return 鑿滃崟鍒楄〃
+     */
+    @Override
+    public List<SysMenu> selectMenuTreeByUserId(Long userId)
+    {
+        List<SysMenu> menus = null;
+        if (SecurityUtils.isAdmin(userId))
+        {
+            menus = menuMapper.selectMenuTreeAll();
+        }
+        else
+        {
+            menus = menuMapper.selectMenuTreeByUserId(userId);
+        }
+        return getChildPerms(menus, 0);
+    }
+
+    /**
+     * 鏍规嵁瑙掕壊ID鏌ヨ鑿滃崟鏍戜俊鎭�
+     * 
+     * @param roleId 瑙掕壊ID
+     * @return 閫変腑鑿滃崟鍒楄〃
+     */
+    @Override
+    public List<Long> selectMenuListByRoleId(Long roleId)
+    {
+        SysRole role = roleMapper.selectRoleById(roleId);
+        return menuMapper.selectMenuListByRoleId(roleId, role.isMenuCheckStrictly());
+    }
+
+    /**
+     * 鏋勫缓鍓嶇璺敱鎵�闇�瑕佺殑鑿滃崟
+     * 
+     * @param menus 鑿滃崟鍒楄〃
+     * @return 璺敱鍒楄〃
+     */
+    @Override
+    public List<RouterVo> buildMenus(List<SysMenu> menus)
+    {
+        List<RouterVo> routers = new LinkedList<RouterVo>();
+        for (SysMenu menu : menus)
+        {
+            RouterVo router = new RouterVo();
+            router.setHidden("1".equals(menu.getVisible()));
+            router.setName(getRouteName(menu));
+            router.setPath(getRouterPath(menu));
+            router.setComponent(getComponent(menu));
+            router.setQuery(menu.getQuery());
+            router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath()));
+            List<SysMenu> cMenus = menu.getChildren();
+            if (StringUtils.isNotEmpty(cMenus) && UserConstants.TYPE_DIR.equals(menu.getMenuType()))
+            {
+                router.setAlwaysShow(true);
+                router.setRedirect("noRedirect");
+                router.setChildren(buildMenus(cMenus));
+            }
+            else if (isMenuFrame(menu))
+            {
+                router.setMeta(null);
+                List<RouterVo> childrenList = new ArrayList<RouterVo>();
+                RouterVo children = new RouterVo();
+                children.setPath(menu.getPath());
+                children.setComponent(menu.getComponent());
+                children.setName(StringUtils.capitalize(menu.getPath()));
+                children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath()));
+                children.setQuery(menu.getQuery());
+                childrenList.add(children);
+                router.setChildren(childrenList);
+            }
+            else if (menu.getParentId().intValue() == 0 && isInnerLink(menu))
+            {
+                router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon()));
+                router.setPath("/");
+                List<RouterVo> childrenList = new ArrayList<RouterVo>();
+                RouterVo children = new RouterVo();
+                String routerPath = innerLinkReplaceEach(menu.getPath());
+                children.setPath(routerPath);
+                children.setComponent(UserConstants.INNER_LINK);
+                children.setName(StringUtils.capitalize(routerPath));
+                children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), menu.getPath()));
+                childrenList.add(children);
+                router.setChildren(childrenList);
+            }
+            routers.add(router);
+        }
+        return routers;
+    }
+
+    /**
+     * 鏋勫缓鍓嶇鎵�闇�瑕佹爲缁撴瀯
+     * 
+     * @param menus 鑿滃崟鍒楄〃
+     * @return 鏍戠粨鏋勫垪琛�
+     */
+    @Override
+    public List<SysMenu> buildMenuTree(List<SysMenu> menus)
+    {
+        List<SysMenu> returnList = new ArrayList<SysMenu>();
+        List<Long> tempList = menus.stream().map(SysMenu::getMenuId).collect(Collectors.toList());
+        for (Iterator<SysMenu> iterator = menus.iterator(); iterator.hasNext();)
+        {
+            SysMenu menu = (SysMenu) iterator.next();
+            // 濡傛灉鏄《绾ц妭鐐�, 閬嶅巻璇ョ埗鑺傜偣鐨勬墍鏈夊瓙鑺傜偣
+            if (!tempList.contains(menu.getParentId()))
+            {
+                recursionFn(menus, menu);
+                returnList.add(menu);
+            }
+        }
+        if (returnList.isEmpty())
+        {
+            returnList = menus;
+        }
+        return returnList;
+    }
+
+    /**
+     * 鏋勫缓鍓嶇鎵�闇�瑕佷笅鎷夋爲缁撴瀯
+     * 
+     * @param menus 鑿滃崟鍒楄〃
+     * @return 涓嬫媺鏍戠粨鏋勫垪琛�
+     */
+    @Override
+    public List<TreeSelect> buildMenuTreeSelect(List<SysMenu> menus)
+    {
+        List<SysMenu> menuTrees = buildMenuTree(menus);
+        return menuTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
+    }
+
+    /**
+     * 鏍规嵁鑿滃崟ID鏌ヨ淇℃伅
+     * 
+     * @param menuId 鑿滃崟ID
+     * @return 鑿滃崟淇℃伅
+     */
+    @Override
+    public SysMenu selectMenuById(Long menuId)
+    {
+        return menuMapper.selectMenuById(menuId);
+    }
+
+    /**
+     * 鏄惁瀛樺湪鑿滃崟瀛愯妭鐐�
+     * 
+     * @param menuId 鑿滃崟ID
+     * @return 缁撴灉
+     */
+    @Override
+    public boolean hasChildByMenuId(Long menuId)
+    {
+        int result = menuMapper.hasChildByMenuId(menuId);
+        return result > 0;
+    }
+
+    /**
+     * 鏌ヨ鑿滃崟浣跨敤鏁伴噺
+     * 
+     * @param menuId 鑿滃崟ID
+     * @return 缁撴灉
+     */
+    @Override
+    public boolean checkMenuExistRole(Long menuId)
+    {
+        int result = roleMenuMapper.checkMenuExistRole(menuId);
+        return result > 0;
+    }
+
+    /**
+     * 鏂板淇濆瓨鑿滃崟淇℃伅
+     * 
+     * @param menu 鑿滃崟淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertMenu(SysMenu menu)
+    {
+        return menuMapper.insertMenu(menu);
+    }
+
+    /**
+     * 淇敼淇濆瓨鑿滃崟淇℃伅
+     * 
+     * @param menu 鑿滃崟淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateMenu(SysMenu menu)
+    {
+        return menuMapper.updateMenu(menu);
+    }
+
+    /**
+     * 鍒犻櫎鑿滃崟绠$悊淇℃伅
+     * 
+     * @param menuId 鑿滃崟ID
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteMenuById(Long menuId)
+    {
+        return menuMapper.deleteMenuById(menuId);
+    }
+
+    /**
+     * 鏍¢獙鑿滃崟鍚嶇О鏄惁鍞竴
+     * 
+     * @param menu 鑿滃崟淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public boolean checkMenuNameUnique(SysMenu menu)
+    {
+        Long menuId = StringUtils.isNull(menu.getMenuId()) ? -1L : menu.getMenuId();
+        SysMenu info = menuMapper.checkMenuNameUnique(menu.getMenuName(), menu.getParentId());
+        if (StringUtils.isNotNull(info) && info.getMenuId().longValue() != menuId.longValue())
+        {
+            return UserConstants.NOT_UNIQUE;
+        }
+        return UserConstants.UNIQUE;
+    }
+
+    /**
+     * 鑾峰彇璺敱鍚嶇О
+     * 
+     * @param menu 鑿滃崟淇℃伅
+     * @return 璺敱鍚嶇О
+     */
+    public String getRouteName(SysMenu menu)
+    {
+        String routerName = StringUtils.capitalize(menu.getPath());
+        // 闈炲閾惧苟涓旀槸涓�绾х洰褰曪紙绫诲瀷涓虹洰褰曪級
+        if (isMenuFrame(menu))
+        {
+            routerName = StringUtils.EMPTY;
+        }
+        return routerName;
+    }
+
+    /**
+     * 鑾峰彇璺敱鍦板潃
+     * 
+     * @param menu 鑿滃崟淇℃伅
+     * @return 璺敱鍦板潃
+     */
+    public String getRouterPath(SysMenu menu)
+    {
+        String routerPath = menu.getPath();
+        // 鍐呴摼鎵撳紑澶栫綉鏂瑰紡
+        if (menu.getParentId().intValue() != 0 && isInnerLink(menu))
+        {
+            routerPath = innerLinkReplaceEach(routerPath);
+        }
+        // 闈炲閾惧苟涓旀槸涓�绾х洰褰曪紙绫诲瀷涓虹洰褰曪級
+        if (0 == menu.getParentId().intValue() && UserConstants.TYPE_DIR.equals(menu.getMenuType())
+                && UserConstants.NO_FRAME.equals(menu.getIsFrame()))
+        {
+            routerPath = "/" + menu.getPath();
+        }
+        // 闈炲閾惧苟涓旀槸涓�绾х洰褰曪紙绫诲瀷涓鸿彍鍗曪級
+        else if (isMenuFrame(menu))
+        {
+            routerPath = "/";
+        }
+        return routerPath;
+    }
+
+    /**
+     * 鑾峰彇缁勪欢淇℃伅
+     * 
+     * @param menu 鑿滃崟淇℃伅
+     * @return 缁勪欢淇℃伅
+     */
+    public String getComponent(SysMenu menu)
+    {
+        String component = UserConstants.LAYOUT;
+        if (StringUtils.isNotEmpty(menu.getComponent()) && !isMenuFrame(menu))
+        {
+            component = menu.getComponent();
+        }
+        else if (StringUtils.isEmpty(menu.getComponent()) && menu.getParentId().intValue() != 0 && isInnerLink(menu))
+        {
+            component = UserConstants.INNER_LINK;
+        }
+        else if (StringUtils.isEmpty(menu.getComponent()) && isParentView(menu))
+        {
+            component = UserConstants.PARENT_VIEW;
+        }
+        return component;
+    }
+
+    /**
+     * 鏄惁涓鸿彍鍗曞唴閮ㄨ烦杞�
+     * 
+     * @param menu 鑿滃崟淇℃伅
+     * @return 缁撴灉
+     */
+    public boolean isMenuFrame(SysMenu menu)
+    {
+        return menu.getParentId().intValue() == 0 && UserConstants.TYPE_MENU.equals(menu.getMenuType())
+                && menu.getIsFrame().equals(UserConstants.NO_FRAME);
+    }
+
+    /**
+     * 鏄惁涓哄唴閾剧粍浠�
+     * 
+     * @param menu 鑿滃崟淇℃伅
+     * @return 缁撴灉
+     */
+    public boolean isInnerLink(SysMenu menu)
+    {
+        return menu.getIsFrame().equals(UserConstants.NO_FRAME) && StringUtils.ishttp(menu.getPath());
+    }
+
+    /**
+     * 鏄惁涓簆arent_view缁勪欢
+     * 
+     * @param menu 鑿滃崟淇℃伅
+     * @return 缁撴灉
+     */
+    public boolean isParentView(SysMenu menu)
+    {
+        return menu.getParentId().intValue() != 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType());
+    }
+
+    /**
+     * 鏍规嵁鐖惰妭鐐圭殑ID鑾峰彇鎵�鏈夊瓙鑺傜偣
+     * 
+     * @param list 鍒嗙被琛�
+     * @param parentId 浼犲叆鐨勭埗鑺傜偣ID
+     * @return String
+     */
+    public List<SysMenu> getChildPerms(List<SysMenu> list, int parentId)
+    {
+        List<SysMenu> returnList = new ArrayList<SysMenu>();
+        for (Iterator<SysMenu> iterator = list.iterator(); iterator.hasNext();)
+        {
+            SysMenu t = (SysMenu) iterator.next();
+            // 涓�銆佹牴鎹紶鍏ョ殑鏌愪釜鐖惰妭鐐笽D,閬嶅巻璇ョ埗鑺傜偣鐨勬墍鏈夊瓙鑺傜偣
+            if (t.getParentId() == parentId)
+            {
+                recursionFn(list, t);
+                returnList.add(t);
+            }
+        }
+        return returnList;
+    }
+
+    /**
+     * 閫掑綊鍒楄〃
+     * 
+     * @param list 鍒嗙被琛�
+     * @param t 瀛愯妭鐐�
+     */
+    private void recursionFn(List<SysMenu> list, SysMenu t)
+    {
+        // 寰楀埌瀛愯妭鐐瑰垪琛�
+        List<SysMenu> childList = getChildList(list, t);
+        t.setChildren(childList);
+        for (SysMenu tChild : childList)
+        {
+            if (hasChild(list, tChild))
+            {
+                recursionFn(list, tChild);
+            }
+        }
+    }
+
+    /**
+     * 寰楀埌瀛愯妭鐐瑰垪琛�
+     */
+    private List<SysMenu> getChildList(List<SysMenu> list, SysMenu t)
+    {
+        List<SysMenu> tlist = new ArrayList<SysMenu>();
+        Iterator<SysMenu> it = list.iterator();
+        while (it.hasNext())
+        {
+            SysMenu n = (SysMenu) it.next();
+            if (n.getParentId().longValue() == t.getMenuId().longValue())
+            {
+                tlist.add(n);
+            }
+        }
+        return tlist;
+    }
+
+    /**
+     * 鍒ゆ柇鏄惁鏈夊瓙鑺傜偣
+     */
+    private boolean hasChild(List<SysMenu> list, SysMenu t)
+    {
+        return getChildList(list, t).size() > 0;
+    }
+
+    /**
+     * 鍐呴摼鍩熷悕鐗规畩瀛楃鏇挎崲
+     * 
+     * @return 鏇挎崲鍚庣殑鍐呴摼鍩熷悕
+     */
+    public String innerLinkReplaceEach(String path)
+    {
+        return StringUtils.replaceEach(path, new String[] { Constants.HTTP, Constants.HTTPS, Constants.WWW, ".", ":" },
+                new String[] { "", "", "", "/", "/" });
+    }
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysNoticeServiceImpl.java b/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysNoticeServiceImpl.java
new file mode 100644
index 0000000..866c09c
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysNoticeServiceImpl.java
@@ -0,0 +1,92 @@
+package com.jcdm.system.service.impl;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.jcdm.system.domain.SysNotice;
+import com.jcdm.system.mapper.SysNoticeMapper;
+import com.jcdm.system.service.ISysNoticeService;
+
+/**
+ * 鍏憡 鏈嶅姟灞傚疄鐜�
+ * 
+ * @author jc
+ */
+@Service
+public class SysNoticeServiceImpl implements ISysNoticeService
+{
+    @Autowired
+    private SysNoticeMapper noticeMapper;
+
+    /**
+     * 鏌ヨ鍏憡淇℃伅
+     * 
+     * @param noticeId 鍏憡ID
+     * @return 鍏憡淇℃伅
+     */
+    @Override
+    public SysNotice selectNoticeById(Long noticeId)
+    {
+        return noticeMapper.selectNoticeById(noticeId);
+    }
+
+    /**
+     * 鏌ヨ鍏憡鍒楄〃
+     * 
+     * @param notice 鍏憡淇℃伅
+     * @return 鍏憡闆嗗悎
+     */
+    @Override
+    public List<SysNotice> selectNoticeList(SysNotice notice)
+    {
+        return noticeMapper.selectNoticeList(notice);
+    }
+
+    /**
+     * 鏂板鍏憡
+     * 
+     * @param notice 鍏憡淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertNotice(SysNotice notice)
+    {
+        return noticeMapper.insertNotice(notice);
+    }
+
+    /**
+     * 淇敼鍏憡
+     * 
+     * @param notice 鍏憡淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateNotice(SysNotice notice)
+    {
+        return noticeMapper.updateNotice(notice);
+    }
+
+    /**
+     * 鍒犻櫎鍏憡瀵硅薄
+     * 
+     * @param noticeId 鍏憡ID
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteNoticeById(Long noticeId)
+    {
+        return noticeMapper.deleteNoticeById(noticeId);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎鍏憡淇℃伅
+     * 
+     * @param noticeIds 闇�瑕佸垹闄ょ殑鍏憡ID
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteNoticeByIds(Long[] noticeIds)
+    {
+        return noticeMapper.deleteNoticeByIds(noticeIds);
+    }
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysOperLogServiceImpl.java b/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysOperLogServiceImpl.java
new file mode 100644
index 0000000..e706d2b
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysOperLogServiceImpl.java
@@ -0,0 +1,76 @@
+package com.jcdm.system.service.impl;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.jcdm.system.domain.SysOperLog;
+import com.jcdm.system.mapper.SysOperLogMapper;
+import com.jcdm.system.service.ISysOperLogService;
+
+/**
+ * 鎿嶄綔鏃ュ織 鏈嶅姟灞傚鐞�
+ * 
+ * @author jc
+ */
+@Service
+public class SysOperLogServiceImpl implements ISysOperLogService
+{
+    @Autowired
+    private SysOperLogMapper operLogMapper;
+
+    /**
+     * 鏂板鎿嶄綔鏃ュ織
+     * 
+     * @param operLog 鎿嶄綔鏃ュ織瀵硅薄
+     */
+    @Override
+    public void insertOperlog(SysOperLog operLog)
+    {
+        operLogMapper.insertOperlog(operLog);
+    }
+
+    /**
+     * 鏌ヨ绯荤粺鎿嶄綔鏃ュ織闆嗗悎
+     * 
+     * @param operLog 鎿嶄綔鏃ュ織瀵硅薄
+     * @return 鎿嶄綔鏃ュ織闆嗗悎
+     */
+    @Override
+    public List<SysOperLog> selectOperLogList(SysOperLog operLog)
+    {
+        return operLogMapper.selectOperLogList(operLog);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎绯荤粺鎿嶄綔鏃ュ織
+     * 
+     * @param operIds 闇�瑕佸垹闄ょ殑鎿嶄綔鏃ュ織ID
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteOperLogByIds(Long[] operIds)
+    {
+        return operLogMapper.deleteOperLogByIds(operIds);
+    }
+
+    /**
+     * 鏌ヨ鎿嶄綔鏃ュ織璇︾粏
+     * 
+     * @param operId 鎿嶄綔ID
+     * @return 鎿嶄綔鏃ュ織瀵硅薄
+     */
+    @Override
+    public SysOperLog selectOperLogById(Long operId)
+    {
+        return operLogMapper.selectOperLogById(operId);
+    }
+
+    /**
+     * 娓呯┖鎿嶄綔鏃ュ織
+     */
+    @Override
+    public void cleanOperLog()
+    {
+        operLogMapper.cleanOperLog();
+    }
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysPostServiceImpl.java b/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysPostServiceImpl.java
new file mode 100644
index 0000000..70cc263
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysPostServiceImpl.java
@@ -0,0 +1,178 @@
+package com.jcdm.system.service.impl;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.jcdm.common.constant.UserConstants;
+import com.jcdm.common.exception.ServiceException;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.system.domain.SysPost;
+import com.jcdm.system.mapper.SysPostMapper;
+import com.jcdm.system.mapper.SysUserPostMapper;
+import com.jcdm.system.service.ISysPostService;
+
+/**
+ * 宀椾綅淇℃伅 鏈嶅姟灞傚鐞�
+ * 
+ * @author jc
+ */
+@Service
+public class SysPostServiceImpl implements ISysPostService
+{
+    @Autowired
+    private SysPostMapper postMapper;
+
+    @Autowired
+    private SysUserPostMapper userPostMapper;
+
+    /**
+     * 鏌ヨ宀椾綅淇℃伅闆嗗悎
+     * 
+     * @param post 宀椾綅淇℃伅
+     * @return 宀椾綅淇℃伅闆嗗悎
+     */
+    @Override
+    public List<SysPost> selectPostList(SysPost post)
+    {
+        return postMapper.selectPostList(post);
+    }
+
+    /**
+     * 鏌ヨ鎵�鏈夊矖浣�
+     * 
+     * @return 宀椾綅鍒楄〃
+     */
+    @Override
+    public List<SysPost> selectPostAll()
+    {
+        return postMapper.selectPostAll();
+    }
+
+    /**
+     * 閫氳繃宀椾綅ID鏌ヨ宀椾綅淇℃伅
+     * 
+     * @param postId 宀椾綅ID
+     * @return 瑙掕壊瀵硅薄淇℃伅
+     */
+    @Override
+    public SysPost selectPostById(Long postId)
+    {
+        return postMapper.selectPostById(postId);
+    }
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鑾峰彇宀椾綅閫夋嫨妗嗗垪琛�
+     * 
+     * @param userId 鐢ㄦ埛ID
+     * @return 閫変腑宀椾綅ID鍒楄〃
+     */
+    @Override
+    public List<Long> selectPostListByUserId(Long userId)
+    {
+        return postMapper.selectPostListByUserId(userId);
+    }
+
+    /**
+     * 鏍¢獙宀椾綅鍚嶇О鏄惁鍞竴
+     * 
+     * @param post 宀椾綅淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public boolean checkPostNameUnique(SysPost post)
+    {
+        Long postId = StringUtils.isNull(post.getPostId()) ? -1L : post.getPostId();
+        SysPost info = postMapper.checkPostNameUnique(post.getPostName());
+        if (StringUtils.isNotNull(info) && info.getPostId().longValue() != postId.longValue())
+        {
+            return UserConstants.NOT_UNIQUE;
+        }
+        return UserConstants.UNIQUE;
+    }
+
+    /**
+     * 鏍¢獙宀椾綅缂栫爜鏄惁鍞竴
+     * 
+     * @param post 宀椾綅淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public boolean checkPostCodeUnique(SysPost post)
+    {
+        Long postId = StringUtils.isNull(post.getPostId()) ? -1L : post.getPostId();
+        SysPost info = postMapper.checkPostCodeUnique(post.getPostCode());
+        if (StringUtils.isNotNull(info) && info.getPostId().longValue() != postId.longValue())
+        {
+            return UserConstants.NOT_UNIQUE;
+        }
+        return UserConstants.UNIQUE;
+    }
+
+    /**
+     * 閫氳繃宀椾綅ID鏌ヨ宀椾綅浣跨敤鏁伴噺
+     * 
+     * @param postId 宀椾綅ID
+     * @return 缁撴灉
+     */
+    @Override
+    public int countUserPostById(Long postId)
+    {
+        return userPostMapper.countUserPostById(postId);
+    }
+
+    /**
+     * 鍒犻櫎宀椾綅淇℃伅
+     * 
+     * @param postId 宀椾綅ID
+     * @return 缁撴灉
+     */
+    @Override
+    public int deletePostById(Long postId)
+    {
+        return postMapper.deletePostById(postId);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎宀椾綅淇℃伅
+     * 
+     * @param postIds 闇�瑕佸垹闄ょ殑宀椾綅ID
+     * @return 缁撴灉
+     */
+    @Override
+    public int deletePostByIds(Long[] postIds)
+    {
+        for (Long postId : postIds)
+        {
+            SysPost post = selectPostById(postId);
+            if (countUserPostById(postId) > 0)
+            {
+                throw new ServiceException(String.format("%1$s宸插垎閰�,涓嶈兘鍒犻櫎", post.getPostName()));
+            }
+        }
+        return postMapper.deletePostByIds(postIds);
+    }
+
+    /**
+     * 鏂板淇濆瓨宀椾綅淇℃伅
+     * 
+     * @param post 宀椾綅淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertPost(SysPost post)
+    {
+        return postMapper.insertPost(post);
+    }
+
+    /**
+     * 淇敼淇濆瓨宀椾綅淇℃伅
+     * 
+     * @param post 宀椾綅淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int updatePost(SysPost post)
+    {
+        return postMapper.updatePost(post);
+    }
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysRoleServiceImpl.java b/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysRoleServiceImpl.java
new file mode 100644
index 0000000..5e17206
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysRoleServiceImpl.java
@@ -0,0 +1,424 @@
+package com.jcdm.system.service.impl;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import com.jcdm.common.annotation.DataScope;
+import com.jcdm.common.constant.UserConstants;
+import com.jcdm.common.core.domain.entity.SysRole;
+import com.jcdm.common.core.domain.entity.SysUser;
+import com.jcdm.common.exception.ServiceException;
+import com.jcdm.common.utils.SecurityUtils;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.common.utils.spring.SpringUtils;
+import com.jcdm.system.domain.SysRoleDept;
+import com.jcdm.system.domain.SysRoleMenu;
+import com.jcdm.system.domain.SysUserRole;
+import com.jcdm.system.mapper.SysRoleDeptMapper;
+import com.jcdm.system.mapper.SysRoleMapper;
+import com.jcdm.system.mapper.SysRoleMenuMapper;
+import com.jcdm.system.mapper.SysUserRoleMapper;
+import com.jcdm.system.service.ISysRoleService;
+
+/**
+ * 瑙掕壊 涓氬姟灞傚鐞�
+ * 
+ * @author jc
+ */
+@Service
+public class SysRoleServiceImpl implements ISysRoleService
+{
+    @Autowired
+    private SysRoleMapper roleMapper;
+
+    @Autowired
+    private SysRoleMenuMapper roleMenuMapper;
+
+    @Autowired
+    private SysUserRoleMapper userRoleMapper;
+
+    @Autowired
+    private SysRoleDeptMapper roleDeptMapper;
+
+    /**
+     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瑙掕壊鏁版嵁
+     * 
+     * @param role 瑙掕壊淇℃伅
+     * @return 瑙掕壊鏁版嵁闆嗗悎淇℃伅
+     */
+    @Override
+    @DataScope(deptAlias = "d")
+    public List<SysRole> selectRoleList(SysRole role)
+    {
+        return roleMapper.selectRoleList(role);
+    }
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鏌ヨ瑙掕壊
+     * 
+     * @param userId 鐢ㄦ埛ID
+     * @return 瑙掕壊鍒楄〃
+     */
+    @Override
+    public List<SysRole> selectRolesByUserId(Long userId)
+    {
+        List<SysRole> userRoles = roleMapper.selectRolePermissionByUserId(userId);
+        List<SysRole> roles = selectRoleAll();
+        for (SysRole role : roles)
+        {
+            for (SysRole userRole : userRoles)
+            {
+                if (role.getRoleId().longValue() == userRole.getRoleId().longValue())
+                {
+                    role.setFlag(true);
+                    break;
+                }
+            }
+        }
+        return roles;
+    }
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鏌ヨ鏉冮檺
+     * 
+     * @param userId 鐢ㄦ埛ID
+     * @return 鏉冮檺鍒楄〃
+     */
+    @Override
+    public Set<String> selectRolePermissionByUserId(Long userId)
+    {
+        List<SysRole> perms = roleMapper.selectRolePermissionByUserId(userId);
+        Set<String> permsSet = new HashSet<>();
+        for (SysRole perm : perms)
+        {
+            if (StringUtils.isNotNull(perm))
+            {
+                permsSet.addAll(Arrays.asList(perm.getRoleKey().trim().split(",")));
+            }
+        }
+        return permsSet;
+    }
+
+    /**
+     * 鏌ヨ鎵�鏈夎鑹�
+     * 
+     * @return 瑙掕壊鍒楄〃
+     */
+    @Override
+    public List<SysRole> selectRoleAll()
+    {
+        return SpringUtils.getAopProxy(this).selectRoleList(new SysRole());
+    }
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鑾峰彇瑙掕壊閫夋嫨妗嗗垪琛�
+     * 
+     * @param userId 鐢ㄦ埛ID
+     * @return 閫変腑瑙掕壊ID鍒楄〃
+     */
+    @Override
+    public List<Long> selectRoleListByUserId(Long userId)
+    {
+        return roleMapper.selectRoleListByUserId(userId);
+    }
+
+    /**
+     * 閫氳繃瑙掕壊ID鏌ヨ瑙掕壊
+     * 
+     * @param roleId 瑙掕壊ID
+     * @return 瑙掕壊瀵硅薄淇℃伅
+     */
+    @Override
+    public SysRole selectRoleById(Long roleId)
+    {
+        return roleMapper.selectRoleById(roleId);
+    }
+
+    /**
+     * 鏍¢獙瑙掕壊鍚嶇О鏄惁鍞竴
+     * 
+     * @param role 瑙掕壊淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public boolean checkRoleNameUnique(SysRole role)
+    {
+        Long roleId = StringUtils.isNull(role.getRoleId()) ? -1L : role.getRoleId();
+        SysRole info = roleMapper.checkRoleNameUnique(role.getRoleName());
+        if (StringUtils.isNotNull(info) && info.getRoleId().longValue() != roleId.longValue())
+        {
+            return UserConstants.NOT_UNIQUE;
+        }
+        return UserConstants.UNIQUE;
+    }
+
+    /**
+     * 鏍¢獙瑙掕壊鏉冮檺鏄惁鍞竴
+     * 
+     * @param role 瑙掕壊淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public boolean checkRoleKeyUnique(SysRole role)
+    {
+        Long roleId = StringUtils.isNull(role.getRoleId()) ? -1L : role.getRoleId();
+        SysRole info = roleMapper.checkRoleKeyUnique(role.getRoleKey());
+        if (StringUtils.isNotNull(info) && info.getRoleId().longValue() != roleId.longValue())
+        {
+            return UserConstants.NOT_UNIQUE;
+        }
+        return UserConstants.UNIQUE;
+    }
+
+    /**
+     * 鏍¢獙瑙掕壊鏄惁鍏佽鎿嶄綔
+     * 
+     * @param role 瑙掕壊淇℃伅
+     */
+    @Override
+    public void checkRoleAllowed(SysRole role)
+    {
+        if (StringUtils.isNotNull(role.getRoleId()) && role.isAdmin())
+        {
+            throw new ServiceException("涓嶅厑璁告搷浣滆秴绾х鐞嗗憳瑙掕壊");
+        }
+    }
+
+    /**
+     * 鏍¢獙瑙掕壊鏄惁鏈夋暟鎹潈闄�
+     * 
+     * @param roleId 瑙掕壊id
+     */
+    @Override
+    public void checkRoleDataScope(Long roleId)
+    {
+        if (!SysUser.isAdmin(SecurityUtils.getUserId()))
+        {
+            SysRole role = new SysRole();
+            role.setRoleId(roleId);
+            List<SysRole> roles = SpringUtils.getAopProxy(this).selectRoleList(role);
+            if (StringUtils.isEmpty(roles))
+            {
+                throw new ServiceException("娌℃湁鏉冮檺璁块棶瑙掕壊鏁版嵁锛�");
+            }
+        }
+    }
+
+    /**
+     * 閫氳繃瑙掕壊ID鏌ヨ瑙掕壊浣跨敤鏁伴噺
+     * 
+     * @param roleId 瑙掕壊ID
+     * @return 缁撴灉
+     */
+    @Override
+    public int countUserRoleByRoleId(Long roleId)
+    {
+        return userRoleMapper.countUserRoleByRoleId(roleId);
+    }
+
+    /**
+     * 鏂板淇濆瓨瑙掕壊淇℃伅
+     * 
+     * @param role 瑙掕壊淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    @Transactional
+    public int insertRole(SysRole role)
+    {
+        // 鏂板瑙掕壊淇℃伅
+        roleMapper.insertRole(role);
+        return insertRoleMenu(role);
+    }
+
+    /**
+     * 淇敼淇濆瓨瑙掕壊淇℃伅
+     * 
+     * @param role 瑙掕壊淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    @Transactional
+    public int updateRole(SysRole role)
+    {
+        // 淇敼瑙掕壊淇℃伅
+        roleMapper.updateRole(role);
+        // 鍒犻櫎瑙掕壊涓庤彍鍗曞叧鑱�
+        roleMenuMapper.deleteRoleMenuByRoleId(role.getRoleId());
+        return insertRoleMenu(role);
+    }
+
+    /**
+     * 淇敼瑙掕壊鐘舵��
+     * 
+     * @param role 瑙掕壊淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateRoleStatus(SysRole role)
+    {
+        return roleMapper.updateRole(role);
+    }
+
+    /**
+     * 淇敼鏁版嵁鏉冮檺淇℃伅
+     * 
+     * @param role 瑙掕壊淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    @Transactional
+    public int authDataScope(SysRole role)
+    {
+        // 淇敼瑙掕壊淇℃伅
+        roleMapper.updateRole(role);
+        // 鍒犻櫎瑙掕壊涓庨儴闂ㄥ叧鑱�
+        roleDeptMapper.deleteRoleDeptByRoleId(role.getRoleId());
+        // 鏂板瑙掕壊鍜岄儴闂ㄤ俊鎭紙鏁版嵁鏉冮檺锛�
+        return insertRoleDept(role);
+    }
+
+    /**
+     * 鏂板瑙掕壊鑿滃崟淇℃伅
+     * 
+     * @param role 瑙掕壊瀵硅薄
+     */
+    public int insertRoleMenu(SysRole role)
+    {
+        int rows = 1;
+        // 鏂板鐢ㄦ埛涓庤鑹茬鐞�
+        List<SysRoleMenu> list = new ArrayList<SysRoleMenu>();
+        for (Long menuId : role.getMenuIds())
+        {
+            SysRoleMenu rm = new SysRoleMenu();
+            rm.setRoleId(role.getRoleId());
+            rm.setMenuId(menuId);
+            list.add(rm);
+        }
+        if (list.size() > 0)
+        {
+            rows = roleMenuMapper.batchRoleMenu(list);
+        }
+        return rows;
+    }
+
+    /**
+     * 鏂板瑙掕壊閮ㄩ棬淇℃伅(鏁版嵁鏉冮檺)
+     *
+     * @param role 瑙掕壊瀵硅薄
+     */
+    public int insertRoleDept(SysRole role)
+    {
+        int rows = 1;
+        // 鏂板瑙掕壊涓庨儴闂紙鏁版嵁鏉冮檺锛夌鐞�
+        List<SysRoleDept> list = new ArrayList<SysRoleDept>();
+        for (Long deptId : role.getDeptIds())
+        {
+            SysRoleDept rd = new SysRoleDept();
+            rd.setRoleId(role.getRoleId());
+            rd.setDeptId(deptId);
+            list.add(rd);
+        }
+        if (list.size() > 0)
+        {
+            rows = roleDeptMapper.batchRoleDept(list);
+        }
+        return rows;
+    }
+
+    /**
+     * 閫氳繃瑙掕壊ID鍒犻櫎瑙掕壊
+     * 
+     * @param roleId 瑙掕壊ID
+     * @return 缁撴灉
+     */
+    @Override
+    @Transactional
+    public int deleteRoleById(Long roleId)
+    {
+        // 鍒犻櫎瑙掕壊涓庤彍鍗曞叧鑱�
+        roleMenuMapper.deleteRoleMenuByRoleId(roleId);
+        // 鍒犻櫎瑙掕壊涓庨儴闂ㄥ叧鑱�
+        roleDeptMapper.deleteRoleDeptByRoleId(roleId);
+        return roleMapper.deleteRoleById(roleId);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎瑙掕壊淇℃伅
+     * 
+     * @param roleIds 闇�瑕佸垹闄ょ殑瑙掕壊ID
+     * @return 缁撴灉
+     */
+    @Override
+    @Transactional
+    public int deleteRoleByIds(Long[] roleIds)
+    {
+        for (Long roleId : roleIds)
+        {
+            checkRoleAllowed(new SysRole(roleId));
+            checkRoleDataScope(roleId);
+            SysRole role = selectRoleById(roleId);
+            if (countUserRoleByRoleId(roleId) > 0)
+            {
+                throw new ServiceException(String.format("%1$s宸插垎閰�,涓嶈兘鍒犻櫎", role.getRoleName()));
+            }
+        }
+        // 鍒犻櫎瑙掕壊涓庤彍鍗曞叧鑱�
+        roleMenuMapper.deleteRoleMenu(roleIds);
+        // 鍒犻櫎瑙掕壊涓庨儴闂ㄥ叧鑱�
+        roleDeptMapper.deleteRoleDept(roleIds);
+        return roleMapper.deleteRoleByIds(roleIds);
+    }
+
+    /**
+     * 鍙栨秷鎺堟潈鐢ㄦ埛瑙掕壊
+     * 
+     * @param userRole 鐢ㄦ埛鍜岃鑹插叧鑱斾俊鎭�
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteAuthUser(SysUserRole userRole)
+    {
+        return userRoleMapper.deleteUserRoleInfo(userRole);
+    }
+
+    /**
+     * 鎵归噺鍙栨秷鎺堟潈鐢ㄦ埛瑙掕壊
+     * 
+     * @param roleId 瑙掕壊ID
+     * @param userIds 闇�瑕佸彇娑堟巿鏉冪殑鐢ㄦ埛鏁版嵁ID
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteAuthUsers(Long roleId, Long[] userIds)
+    {
+        return userRoleMapper.deleteUserRoleInfos(roleId, userIds);
+    }
+
+    /**
+     * 鎵归噺閫夋嫨鎺堟潈鐢ㄦ埛瑙掕壊
+     * 
+     * @param roleId 瑙掕壊ID
+     * @param userIds 闇�瑕佹巿鏉冪殑鐢ㄦ埛鏁版嵁ID
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertAuthUsers(Long roleId, Long[] userIds)
+    {
+        // 鏂板鐢ㄦ埛涓庤鑹茬鐞�
+        List<SysUserRole> list = new ArrayList<SysUserRole>();
+        for (Long userId : userIds)
+        {
+            SysUserRole ur = new SysUserRole();
+            ur.setUserId(userId);
+            ur.setRoleId(roleId);
+            list.add(ur);
+        }
+        return userRoleMapper.batchUserRole(list);
+    }
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysUserOnlineServiceImpl.java b/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysUserOnlineServiceImpl.java
new file mode 100644
index 0000000..34f67f2
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysUserOnlineServiceImpl.java
@@ -0,0 +1,96 @@
+package com.jcdm.system.service.impl;
+
+import org.springframework.stereotype.Service;
+import com.jcdm.common.core.domain.model.LoginUser;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.system.domain.SysUserOnline;
+import com.jcdm.system.service.ISysUserOnlineService;
+
+/**
+ * 鍦ㄧ嚎鐢ㄦ埛 鏈嶅姟灞傚鐞�
+ * 
+ * @author jc
+ */
+@Service
+public class SysUserOnlineServiceImpl implements ISysUserOnlineService
+{
+    /**
+     * 閫氳繃鐧诲綍鍦板潃鏌ヨ淇℃伅
+     * 
+     * @param ipaddr 鐧诲綍鍦板潃
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 鍦ㄧ嚎鐢ㄦ埛淇℃伅
+     */
+    @Override
+    public SysUserOnline selectOnlineByIpaddr(String ipaddr, LoginUser user)
+    {
+        if (StringUtils.equals(ipaddr, user.getIpaddr()))
+        {
+            return loginUserToUserOnline(user);
+        }
+        return null;
+    }
+
+    /**
+     * 閫氳繃鐢ㄦ埛鍚嶇О鏌ヨ淇℃伅
+     * 
+     * @param userName 鐢ㄦ埛鍚嶇О
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 鍦ㄧ嚎鐢ㄦ埛淇℃伅
+     */
+    @Override
+    public SysUserOnline selectOnlineByUserName(String userName, LoginUser user)
+    {
+        if (StringUtils.equals(userName, user.getUsername()))
+        {
+            return loginUserToUserOnline(user);
+        }
+        return null;
+    }
+
+    /**
+     * 閫氳繃鐧诲綍鍦板潃/鐢ㄦ埛鍚嶇О鏌ヨ淇℃伅
+     * 
+     * @param ipaddr 鐧诲綍鍦板潃
+     * @param userName 鐢ㄦ埛鍚嶇О
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 鍦ㄧ嚎鐢ㄦ埛淇℃伅
+     */
+    @Override
+    public SysUserOnline selectOnlineByInfo(String ipaddr, String userName, LoginUser user)
+    {
+        if (StringUtils.equals(ipaddr, user.getIpaddr()) && StringUtils.equals(userName, user.getUsername()))
+        {
+            return loginUserToUserOnline(user);
+        }
+        return null;
+    }
+
+    /**
+     * 璁剧疆鍦ㄧ嚎鐢ㄦ埛淇℃伅
+     * 
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 鍦ㄧ嚎鐢ㄦ埛
+     */
+    @Override
+    public SysUserOnline loginUserToUserOnline(LoginUser user)
+    {
+        if (StringUtils.isNull(user) || StringUtils.isNull(user.getUser()))
+        {
+            return null;
+        }
+        SysUserOnline sysUserOnline = new SysUserOnline();
+        sysUserOnline.setTokenId(user.getToken());
+        sysUserOnline.setUserName(user.getUsername());
+        sysUserOnline.setIpaddr(user.getIpaddr());
+        sysUserOnline.setLoginLocation(user.getLoginLocation());
+        sysUserOnline.setBrowser(user.getBrowser());
+        sysUserOnline.setOs(user.getOs());
+        sysUserOnline.setLoginTime(user.getLoginTime());
+        if (StringUtils.isNotNull(user.getUser().getDept()))
+        {
+            sysUserOnline.setDeptName(user.getUser().getDept().getDeptName());
+        }
+        return sysUserOnline;
+    }
+}
diff --git a/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysUserServiceImpl.java b/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysUserServiceImpl.java
new file mode 100644
index 0000000..35c5935
--- /dev/null
+++ b/jcdm-system/src/main/java/com/jcdm/system/service/impl/SysUserServiceImpl.java
@@ -0,0 +1,544 @@
+package com.jcdm.system.service.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.validation.Validator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+import com.jcdm.common.annotation.DataScope;
+import com.jcdm.common.constant.UserConstants;
+import com.jcdm.common.core.domain.entity.SysRole;
+import com.jcdm.common.core.domain.entity.SysUser;
+import com.jcdm.common.exception.ServiceException;
+import com.jcdm.common.utils.SecurityUtils;
+import com.jcdm.common.utils.StringUtils;
+import com.jcdm.common.utils.bean.BeanValidators;
+import com.jcdm.common.utils.spring.SpringUtils;
+import com.jcdm.system.domain.SysPost;
+import com.jcdm.system.domain.SysUserPost;
+import com.jcdm.system.domain.SysUserRole;
+import com.jcdm.system.mapper.SysPostMapper;
+import com.jcdm.system.mapper.SysRoleMapper;
+import com.jcdm.system.mapper.SysUserMapper;
+import com.jcdm.system.mapper.SysUserPostMapper;
+import com.jcdm.system.mapper.SysUserRoleMapper;
+import com.jcdm.system.service.ISysConfigService;
+import com.jcdm.system.service.ISysUserService;
+
+/**
+ * 鐢ㄦ埛 涓氬姟灞傚鐞�
+ * 
+ * @author jc
+ */
+@Service
+public class SysUserServiceImpl implements ISysUserService
+{
+    private static final Logger log = LoggerFactory.getLogger(SysUserServiceImpl.class);
+
+    @Autowired
+    private SysUserMapper userMapper;
+
+    @Autowired
+    private SysRoleMapper roleMapper;
+
+    @Autowired
+    private SysPostMapper postMapper;
+
+    @Autowired
+    private SysUserRoleMapper userRoleMapper;
+
+    @Autowired
+    private SysUserPostMapper userPostMapper;
+
+    @Autowired
+    private ISysConfigService configService;
+
+    @Autowired
+    protected Validator validator;
+
+    /**
+     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ鐢ㄦ埛鍒楄〃
+     * 
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
+     */
+    @Override
+    @DataScope(deptAlias = "d", userAlias = "u")
+    public List<SysUser> selectUserList(SysUser user)
+    {
+        return userMapper.selectUserList(user);
+    }
+
+    /**
+     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ宸插垎閰嶇敤鎴疯鑹插垪琛�
+     * 
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
+     */
+    @Override
+    @DataScope(deptAlias = "d", userAlias = "u")
+    public List<SysUser> selectAllocatedList(SysUser user)
+    {
+        return userMapper.selectAllocatedList(user);
+    }
+
+    /**
+     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ鏈垎閰嶇敤鎴疯鑹插垪琛�
+     * 
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
+     */
+    @Override
+    @DataScope(deptAlias = "d", userAlias = "u")
+    public List<SysUser> selectUnallocatedList(SysUser user)
+    {
+        return userMapper.selectUnallocatedList(user);
+    }
+
+    /**
+     * 閫氳繃鐢ㄦ埛鍚嶆煡璇㈢敤鎴�
+     * 
+     * @param userName 鐢ㄦ埛鍚�
+     * @return 鐢ㄦ埛瀵硅薄淇℃伅
+     */
+    @Override
+    public SysUser selectUserByUserName(String userName)
+    {
+        return userMapper.selectUserByUserName(userName);
+    }
+
+    /**
+     * 閫氳繃鐢ㄦ埛ID鏌ヨ鐢ㄦ埛
+     * 
+     * @param userId 鐢ㄦ埛ID
+     * @return 鐢ㄦ埛瀵硅薄淇℃伅
+     */
+    @Override
+    public SysUser selectUserById(Long userId)
+    {
+        return userMapper.selectUserById(userId);
+    }
+
+    /**
+     * 鏌ヨ鐢ㄦ埛鎵�灞炶鑹茬粍
+     * 
+     * @param userName 鐢ㄦ埛鍚�
+     * @return 缁撴灉
+     */
+    @Override
+    public String selectUserRoleGroup(String userName)
+    {
+        List<SysRole> list = roleMapper.selectRolesByUserName(userName);
+        if (CollectionUtils.isEmpty(list))
+        {
+            return StringUtils.EMPTY;
+        }
+        return list.stream().map(SysRole::getRoleName).collect(Collectors.joining(","));
+    }
+
+    /**
+     * 鏌ヨ鐢ㄦ埛鎵�灞炲矖浣嶇粍
+     * 
+     * @param userName 鐢ㄦ埛鍚�
+     * @return 缁撴灉
+     */
+    @Override
+    public String selectUserPostGroup(String userName)
+    {
+        List<SysPost> list = postMapper.selectPostsByUserName(userName);
+        if (CollectionUtils.isEmpty(list))
+        {
+            return StringUtils.EMPTY;
+        }
+        return list.stream().map(SysPost::getPostName).collect(Collectors.joining(","));
+    }
+
+    /**
+     * 鏍¢獙鐢ㄦ埛鍚嶇О鏄惁鍞竴
+     * 
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public boolean checkUserNameUnique(SysUser user)
+    {
+        Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
+        SysUser info = userMapper.checkUserNameUnique(user.getUserName());
+        if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue())
+        {
+            return UserConstants.NOT_UNIQUE;
+        }
+        return UserConstants.UNIQUE;
+    }
+
+    /**
+     * 鏍¢獙鎵嬫満鍙风爜鏄惁鍞竴
+     *
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return
+     */
+    @Override
+    public boolean checkPhoneUnique(SysUser user)
+    {
+        Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
+        SysUser info = userMapper.checkPhoneUnique(user.getPhonenumber());
+        if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue())
+        {
+            return UserConstants.NOT_UNIQUE;
+        }
+        return UserConstants.UNIQUE;
+    }
+
+    /**
+     * 鏍¢獙email鏄惁鍞竴
+     *
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return
+     */
+    @Override
+    public boolean checkEmailUnique(SysUser user)
+    {
+        Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
+        SysUser info = userMapper.checkEmailUnique(user.getEmail());
+        if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue())
+        {
+            return UserConstants.NOT_UNIQUE;
+        }
+        return UserConstants.UNIQUE;
+    }
+
+    /**
+     * 鏍¢獙鐢ㄦ埛鏄惁鍏佽鎿嶄綔
+     * 
+     * @param user 鐢ㄦ埛淇℃伅
+     */
+    @Override
+    public void checkUserAllowed(SysUser user)
+    {
+        if (StringUtils.isNotNull(user.getUserId()) && user.isAdmin())
+        {
+            throw new ServiceException("涓嶅厑璁告搷浣滆秴绾х鐞嗗憳鐢ㄦ埛");
+        }
+    }
+
+    /**
+     * 鏍¢獙鐢ㄦ埛鏄惁鏈夋暟鎹潈闄�
+     * 
+     * @param userId 鐢ㄦ埛id
+     */
+    @Override
+    public void checkUserDataScope(Long userId)
+    {
+        if (!SysUser.isAdmin(SecurityUtils.getUserId()))
+        {
+            SysUser user = new SysUser();
+            user.setUserId(userId);
+            List<SysUser> users = SpringUtils.getAopProxy(this).selectUserList(user);
+            if (StringUtils.isEmpty(users))
+            {
+                throw new ServiceException("娌℃湁鏉冮檺璁块棶鐢ㄦ埛鏁版嵁锛�");
+            }
+        }
+    }
+
+    /**
+     * 鏂板淇濆瓨鐢ㄦ埛淇℃伅
+     * 
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    @Transactional
+    public int insertUser(SysUser user)
+    {
+        // 鏂板鐢ㄦ埛淇℃伅
+        int rows = userMapper.insertUser(user);
+        // 鏂板鐢ㄦ埛宀椾綅鍏宠仈
+        insertUserPost(user);
+        // 鏂板鐢ㄦ埛涓庤鑹茬鐞�
+        insertUserRole(user);
+        return rows;
+    }
+
+    /**
+     * 娉ㄥ唽鐢ㄦ埛淇℃伅
+     * 
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public boolean registerUser(SysUser user)
+    {
+        return userMapper.insertUser(user) > 0;
+    }
+
+    /**
+     * 淇敼淇濆瓨鐢ㄦ埛淇℃伅
+     * 
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    @Transactional
+    public int updateUser(SysUser user)
+    {
+        Long userId = user.getUserId();
+        // 鍒犻櫎鐢ㄦ埛涓庤鑹插叧鑱�
+        userRoleMapper.deleteUserRoleByUserId(userId);
+        // 鏂板鐢ㄦ埛涓庤鑹茬鐞�
+        insertUserRole(user);
+        // 鍒犻櫎鐢ㄦ埛涓庡矖浣嶅叧鑱�
+        userPostMapper.deleteUserPostByUserId(userId);
+        // 鏂板鐢ㄦ埛涓庡矖浣嶇鐞�
+        insertUserPost(user);
+        return userMapper.updateUser(user);
+    }
+
+    /**
+     * 鐢ㄦ埛鎺堟潈瑙掕壊
+     * 
+     * @param userId 鐢ㄦ埛ID
+     * @param roleIds 瑙掕壊缁�
+     */
+    @Override
+    @Transactional
+    public void insertUserAuth(Long userId, Long[] roleIds)
+    {
+        userRoleMapper.deleteUserRoleByUserId(userId);
+        insertUserRole(userId, roleIds);
+    }
+
+    /**
+     * 淇敼鐢ㄦ埛鐘舵��
+     * 
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateUserStatus(SysUser user)
+    {
+        return userMapper.updateUser(user);
+    }
+
+    /**
+     * 淇敼鐢ㄦ埛鍩烘湰淇℃伅
+     * 
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateUserProfile(SysUser user)
+    {
+        return userMapper.updateUser(user);
+    }
+
+    /**
+     * 淇敼鐢ㄦ埛澶村儚
+     * 
+     * @param userName 鐢ㄦ埛鍚�
+     * @param avatar 澶村儚鍦板潃
+     * @return 缁撴灉
+     */
+    @Override
+    public boolean updateUserAvatar(String userName, String avatar)
+    {
+        return userMapper.updateUserAvatar(userName, avatar) > 0;
+    }
+
+    /**
+     * 閲嶇疆鐢ㄦ埛瀵嗙爜
+     * 
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int resetPwd(SysUser user)
+    {
+        return userMapper.updateUser(user);
+    }
+
+    /**
+     * 閲嶇疆鐢ㄦ埛瀵嗙爜
+     * 
+     * @param userName 鐢ㄦ埛鍚�
+     * @param password 瀵嗙爜
+     * @return 缁撴灉
+     */
+    @Override
+    public int resetUserPwd(String userName, String password)
+    {
+        return userMapper.resetUserPwd(userName, password);
+    }
+
+    /**
+     * 鏂板鐢ㄦ埛瑙掕壊淇℃伅
+     * 
+     * @param user 鐢ㄦ埛瀵硅薄
+     */
+    public void insertUserRole(SysUser user)
+    {
+        this.insertUserRole(user.getUserId(), user.getRoleIds());
+    }
+
+    /**
+     * 鏂板鐢ㄦ埛宀椾綅淇℃伅
+     * 
+     * @param user 鐢ㄦ埛瀵硅薄
+     */
+    public void insertUserPost(SysUser user)
+    {
+        Long[] posts = user.getPostIds();
+        if (StringUtils.isNotEmpty(posts))
+        {
+            // 鏂板鐢ㄦ埛涓庡矖浣嶇鐞�
+            List<SysUserPost> list = new ArrayList<SysUserPost>(posts.length);
+            for (Long postId : posts)
+            {
+                SysUserPost up = new SysUserPost();
+                up.setUserId(user.getUserId());
+                up.setPostId(postId);
+                list.add(up);
+            }
+            userPostMapper.batchUserPost(list);
+        }
+    }
+
+    /**
+     * 鏂板鐢ㄦ埛瑙掕壊淇℃伅
+     * 
+     * @param userId 鐢ㄦ埛ID
+     * @param roleIds 瑙掕壊缁�
+     */
+    public void insertUserRole(Long userId, Long[] roleIds)
+    {
+        if (StringUtils.isNotEmpty(roleIds))
+        {
+            // 鏂板鐢ㄦ埛涓庤鑹茬鐞�
+            List<SysUserRole> list = new ArrayList<SysUserRole>(roleIds.length);
+            for (Long roleId : roleIds)
+            {
+                SysUserRole ur = new SysUserRole();
+                ur.setUserId(userId);
+                ur.setRoleId(roleId);
+                list.add(ur);
+            }
+            userRoleMapper.batchUserRole(list);
+        }
+    }
+
+    /**
+     * 閫氳繃鐢ㄦ埛ID鍒犻櫎鐢ㄦ埛
+     * 
+     * @param userId 鐢ㄦ埛ID
+     * @return 缁撴灉
+     */
+    @Override
+    @Transactional
+    public int deleteUserById(Long userId)
+    {
+        // 鍒犻櫎鐢ㄦ埛涓庤鑹插叧鑱�
+        userRoleMapper.deleteUserRoleByUserId(userId);
+        // 鍒犻櫎鐢ㄦ埛涓庡矖浣嶈〃
+        userPostMapper.deleteUserPostByUserId(userId);
+        return userMapper.deleteUserById(userId);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎鐢ㄦ埛淇℃伅
+     * 
+     * @param userIds 闇�瑕佸垹闄ょ殑鐢ㄦ埛ID
+     * @return 缁撴灉
+     */
+    @Override
+    @Transactional
+    public int deleteUserByIds(Long[] userIds)
+    {
+        for (Long userId : userIds)
+        {
+            checkUserAllowed(new SysUser(userId));
+            checkUserDataScope(userId);
+        }
+        // 鍒犻櫎鐢ㄦ埛涓庤鑹插叧鑱�
+        userRoleMapper.deleteUserRole(userIds);
+        // 鍒犻櫎鐢ㄦ埛涓庡矖浣嶅叧鑱�
+        userPostMapper.deleteUserPost(userIds);
+        return userMapper.deleteUserByIds(userIds);
+    }
+
+    /**
+     * 瀵煎叆鐢ㄦ埛鏁版嵁
+     * 
+     * @param userList 鐢ㄦ埛鏁版嵁鍒楄〃
+     * @param isUpdateSupport 鏄惁鏇存柊鏀寔锛屽鏋滃凡瀛樺湪锛屽垯杩涜鏇存柊鏁版嵁
+     * @param operName 鎿嶄綔鐢ㄦ埛
+     * @return 缁撴灉
+     */
+    @Override
+    public String importUser(List<SysUser> userList, Boolean isUpdateSupport, String operName)
+    {
+        if (StringUtils.isNull(userList) || userList.size() == 0)
+        {
+            throw new ServiceException("瀵煎叆鐢ㄦ埛鏁版嵁涓嶈兘涓虹┖锛�");
+        }
+        int successNum = 0;
+        int failureNum = 0;
+        StringBuilder successMsg = new StringBuilder();
+        StringBuilder failureMsg = new StringBuilder();
+        String password = configService.selectConfigByKey("sys.user.initPassword");
+        for (SysUser user : userList)
+        {
+            try
+            {
+                // 楠岃瘉鏄惁瀛樺湪杩欎釜鐢ㄦ埛
+                SysUser u = userMapper.selectUserByUserName(user.getUserName());
+                if (StringUtils.isNull(u))
+                {
+                    BeanValidators.validateWithException(validator, user);
+                    user.setPassword(SecurityUtils.encryptPassword(password));
+                    user.setCreateBy(operName);
+                    userMapper.insertUser(user);
+                    successNum++;
+                    successMsg.append("<br/>" + successNum + "銆佽处鍙� " + user.getUserName() + " 瀵煎叆鎴愬姛");
+                }
+                else if (isUpdateSupport)
+                {
+                    BeanValidators.validateWithException(validator, user);
+                    checkUserAllowed(u);
+                    checkUserDataScope(u.getUserId());
+                    user.setUserId(u.getUserId());
+                    user.setUpdateBy(operName);
+                    userMapper.updateUser(user);
+                    successNum++;
+                    successMsg.append("<br/>" + successNum + "銆佽处鍙� " + user.getUserName() + " 鏇存柊鎴愬姛");
+                }
+                else
+                {
+                    failureNum++;
+                    failureMsg.append("<br/>" + failureNum + "銆佽处鍙� " + user.getUserName() + " 宸插瓨鍦�");
+                }
+            }
+            catch (Exception e)
+            {
+                failureNum++;
+                String msg = "<br/>" + failureNum + "銆佽处鍙� " + user.getUserName() + " 瀵煎叆澶辫触锛�";
+                failureMsg.append(msg + e.getMessage());
+                log.error(msg, e);
+            }
+        }
+        if (failureNum > 0)
+        {
+            failureMsg.insert(0, "寰堟姳姝夛紝瀵煎叆澶辫触锛佸叡 " + failureNum + " 鏉℃暟鎹牸寮忎笉姝g‘锛岄敊璇涓嬶細");
+            throw new ServiceException(failureMsg.toString());
+        }
+        else
+        {
+            successMsg.insert(0, "鎭枩鎮紝鏁版嵁宸插叏閮ㄥ鍏ユ垚鍔燂紒鍏� " + successNum + " 鏉★紝鏁版嵁濡備笅锛�");
+        }
+        return successMsg.toString();
+    }
+}
diff --git a/jcdm-system/src/main/resources/mapper/system/SysConfigMapper.xml b/jcdm-system/src/main/resources/mapper/system/SysConfigMapper.xml
new file mode 100644
index 0000000..6459985
--- /dev/null
+++ b/jcdm-system/src/main/resources/mapper/system/SysConfigMapper.xml
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.system.mapper.SysConfigMapper">
+    
+    <resultMap type="SysConfig" id="SysConfigResult">
+    	<id     property="configId"      column="config_id"      />
+        <result property="configName"    column="config_name"    />
+        <result property="configKey"     column="config_key"     />
+        <result property="configValue"   column="config_value"   />
+        <result property="configType"    column="config_type"    />
+        <result property="createBy"      column="create_by"      />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateBy"      column="update_by"      />
+        <result property="updateTime"    column="update_time"    />
+    </resultMap>
+    
+    <sql id="selectConfigVo">
+        select config_id, config_name, config_key, config_value, config_type, create_by, create_time, update_by, update_time, remark 
+		from sys_config
+    </sql>
+    
+    <!-- 鏌ヨ鏉′欢 -->
+	<sql id="sqlwhereSearch">
+		<where>
+			<if test="configId !=null">
+				and config_id = #{configId}
+			</if>
+			<if test="configKey !=null and configKey != ''">
+				and config_key = #{configKey}
+			</if>
+		</where>
+	</sql>
+    
+    <select id="selectConfig" parameterType="SysConfig" resultMap="SysConfigResult">
+        <include refid="selectConfigVo"/>
+        <include refid="sqlwhereSearch"/>
+    </select>
+    
+    <select id="selectConfigList" parameterType="SysConfig" resultMap="SysConfigResult">
+        <include refid="selectConfigVo"/>
+        <where>
+			<if test="configName != null and configName != ''">
+				AND config_name like concat('%', #{configName}, '%')
+			</if>
+			<if test="configType != null and configType != ''">
+				AND config_type = #{configType}
+			</if>
+			<if test="configKey != null and configKey != ''">
+				AND config_key like concat('%', #{configKey}, '%')
+			</if>
+			<if test="params.beginTime != null and params.beginTime != ''"><!-- 寮�濮嬫椂闂存绱� -->
+				and date_format(create_time,'%y%m%d') &gt;= date_format(#{params.beginTime},'%y%m%d')
+			</if>
+			<if test="params.endTime != null and params.endTime != ''"><!-- 缁撴潫鏃堕棿妫�绱� -->
+				and date_format(create_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
+			</if>
+		</where>
+    </select>
+    
+    <select id="selectConfigById" parameterType="Long" resultMap="SysConfigResult">
+        <include refid="selectConfigVo"/>
+        where config_id = #{configId}
+    </select>
+	
+    <select id="checkConfigKeyUnique" parameterType="String" resultMap="SysConfigResult">
+        <include refid="selectConfigVo"/>
+        where config_key = #{configKey} limit 1
+    </select>
+    
+    <insert id="insertConfig" parameterType="SysConfig">
+        insert into sys_config (
+			<if test="configName != null and configName != '' ">config_name,</if>
+			<if test="configKey != null and configKey != '' ">config_key,</if>
+			<if test="configValue != null and configValue != '' ">config_value,</if>
+			<if test="configType != null and configType != '' ">config_type,</if>
+			<if test="createBy != null and createBy != ''">create_by,</if>
+			<if test="remark != null and remark != ''">remark,</if>
+ 			create_time
+        )values(
+			<if test="configName != null and configName != ''">#{configName},</if>
+			<if test="configKey != null and configKey != ''">#{configKey},</if>
+			<if test="configValue != null and configValue != ''">#{configValue},</if>
+			<if test="configType != null and configType != ''">#{configType},</if>
+			<if test="createBy != null and createBy != ''">#{createBy},</if>
+			<if test="remark != null and remark != ''">#{remark},</if>
+ 			getdate()
+		)
+    </insert>
+	 
+    <update id="updateConfig" parameterType="SysConfig">
+        update sys_config 
+        <set>
+            <if test="configName != null and configName != ''">config_name = #{configName},</if>
+            <if test="configKey != null and configKey != ''">config_key = #{configKey},</if>
+            <if test="configValue != null and configValue != ''">config_value = #{configValue},</if>
+            <if test="configType != null and configType != ''">config_type = #{configType},</if>
+            <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
+            <if test="remark != null">remark = #{remark},</if>
+ 			update_time = getdate()
+        </set>
+        where config_id = #{configId}
+    </update>
+	
+    <delete id="deleteConfigById" parameterType="Long">
+        delete from sys_config where config_id = #{configId}
+    </delete>
+    
+    <delete id="deleteConfigByIds" parameterType="Long">
+        delete from sys_config where config_id in 
+        <foreach item="configId" collection="array" open="(" separator="," close=")">
+        	#{configId}
+        </foreach>
+    </delete>
+    
+</mapper>
\ No newline at end of file
diff --git a/jcdm-system/src/main/resources/mapper/system/SysDeptMapper.xml b/jcdm-system/src/main/resources/mapper/system/SysDeptMapper.xml
new file mode 100644
index 0000000..501b343
--- /dev/null
+++ b/jcdm-system/src/main/resources/mapper/system/SysDeptMapper.xml
@@ -0,0 +1,160 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+		PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+		"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.system.mapper.SysDeptMapper">
+
+	<resultMap type="SysDept" id="SysDeptResult">
+		<id     property="deptId"     column="dept_id"     />
+		<result property="parentId"   column="parent_id"   />
+		<result property="ancestors"  column="ancestors"   />
+		<result property="deptName"   column="dept_name"   />
+		<result property="orderNum"   column="order_num"   />
+		<result property="leader"     column="leader"      />
+		<result property="phone"      column="phone"       />
+		<result property="email"      column="email"       />
+		<result property="status"     column="status"      />
+		<result property="delFlag"    column="del_flag"    />
+		<result property="parentName" column="parent_name" />
+		<result property="createBy"   column="create_by"   />
+		<result property="createTime" column="create_time" />
+		<result property="updateBy"   column="update_by"   />
+		<result property="updateTime" column="update_time" />
+	</resultMap>
+
+	<sql id="selectDeptVo">
+		select d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.phone, d.email, d.status, d.del_flag, d.create_by, d.create_time
+		from sys_dept d
+	</sql>
+
+	<select id="selectDeptList" parameterType="SysDept" resultMap="SysDeptResult">
+		<include refid="selectDeptVo"/>
+		where d.del_flag = '0'
+		<if test="deptId != null and deptId != 0">
+			AND dept_id = #{deptId}
+		</if>
+		<if test="parentId != null and parentId != 0">
+			AND parent_id = #{parentId}
+		</if>
+		<if test="deptName != null and deptName != ''">
+			AND dept_name like concat('%', #{deptName}, '%')
+		</if>
+		<if test="status != null and status != ''">
+			AND status = #{status}
+		</if>
+		<!-- 鏁版嵁鑼冨洿杩囨护 -->
+		${params.dataScope}
+		order by d.parent_id, d.order_num
+	</select>
+
+	<select id="selectDeptListByRoleId" resultType="Long">
+		select d.dept_id
+		from sys_dept d
+		left join sys_role_dept rd on d.dept_id = rd.dept_id
+		where rd.role_id = #{roleId}
+		<if test="deptCheckStrictly">
+			and d.dept_id not in (select d.parent_id from sys_dept d inner join sys_role_dept rd on d.dept_id = rd.dept_id and rd.role_id = #{roleId})
+		</if>
+		order by d.parent_id, d.order_num
+	</select>
+
+	<select id="selectDeptById" parameterType="Long" resultMap="SysDeptResult">
+		select d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.phone, d.email, d.status,
+			   (select dept_name from sys_dept where dept_id = d.parent_id) parent_name
+		from sys_dept d
+		where d.dept_id = #{deptId}
+	</select>
+
+	<select id="checkDeptExistUser" parameterType="Long" resultType="int">
+		select count(1) from sys_user where dept_id = #{deptId} and del_flag = '0'
+	</select>
+
+	<select id="hasChildByDeptId" parameterType="Long" resultType="int">
+		select top(1) count(1) from sys_dept
+		where del_flag = '0' and parent_id = #{deptId}
+	</select>
+
+	<select id="selectChildrenDeptById" parameterType="Long" resultMap="SysDeptResult">
+		select * from sys_dept where charindex(',' + convert(nvarchar, #{deptId}), ',' + ancestors) > 0
+	</select>
+
+	<select id="selectNormalChildrenDeptById" parameterType="Long" resultType="int">
+		select count(*) from sys_dept where status = 0 and del_flag = '0' and charindex(',' + convert(nvarchar, #{deptId}), ',' + ancestors) > 0
+	</select>
+
+	<select id="checkDeptNameUnique" resultMap="SysDeptResult">
+		select top(1) d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.phone, d.email, d.status, d.del_flag, d.create_by, d.create_time
+		from sys_dept d
+		where dept_name=#{deptName} and parent_id = #{parentId} and del_flag = '0'
+	</select>
+
+	<insert id="insertDept" parameterType="SysDept">
+		insert into sys_dept(
+		<if test="deptId != null and deptId != 0">dept_id,</if>
+		<if test="parentId != null and parentId != 0">parent_id,</if>
+		<if test="deptName != null and deptName != ''">dept_name,</if>
+		<if test="ancestors != null and ancestors != ''">ancestors,</if>
+		<if test="orderNum != null">order_num,</if>
+		<if test="leader != null and leader != ''">leader,</if>
+		<if test="phone != null and phone != ''">phone,</if>
+		<if test="email != null and email != ''">email,</if>
+		<if test="status != null">status,</if>
+		<if test="createBy != null and createBy != ''">create_by,</if>
+		create_time
+		)values(
+		<if test="deptId != null and deptId != 0">#{deptId},</if>
+		<if test="parentId != null and parentId != 0">#{parentId},</if>
+		<if test="deptName != null and deptName != ''">#{deptName},</if>
+		<if test="ancestors != null and ancestors != ''">#{ancestors},</if>
+		<if test="orderNum != null">#{orderNum},</if>
+		<if test="leader != null and leader != ''">#{leader},</if>
+		<if test="phone != null and phone != ''">#{phone},</if>
+		<if test="email != null and email != ''">#{email},</if>
+		<if test="status != null">#{status},</if>
+		<if test="createBy != null and createBy != ''">#{createBy},</if>
+		getdate()
+		)
+	</insert>
+
+	<update id="updateDept" parameterType="SysDept">
+		update sys_dept
+		<set>
+			<if test="parentId != null and parentId != 0">parent_id = #{parentId},</if>
+			<if test="deptName != null and deptName != ''">dept_name = #{deptName},</if>
+			<if test="ancestors != null and ancestors != ''">ancestors = #{ancestors},</if>
+			<if test="orderNum != null">order_num = #{orderNum},</if>
+			<if test="leader != null">leader = #{leader},</if>
+			<if test="phone != null">phone = #{phone},</if>
+			<if test="email != null">email = #{email},</if>
+			<if test="status != null and status != ''">status = #{status},</if>
+			<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
+			update_time = getdate()
+		</set>
+		where dept_id = #{deptId}
+	</update>
+
+	<update id="updateDeptChildren" parameterType="java.util.List">
+		update sys_dept set ancestors =
+		<foreach collection="depts" item="item" index="index"
+				 separator=" " open="case dept_id" close="end">
+			when #{item.deptId} then #{item.ancestors}
+		</foreach>
+		where dept_id in
+		<foreach collection="depts" item="item" index="index"
+				 separator="," open="(" close=")">
+			#{item.deptId}
+		</foreach>
+	</update>
+
+	<update id="updateDeptStatusNormal" parameterType="Long">
+		update sys_dept set status = '0' where dept_id in
+		<foreach collection="array" item="deptId" open="(" separator="," close=")">
+			#{deptId}
+		</foreach>
+	</update>
+
+	<delete id="deleteDeptById" parameterType="Long">
+		update sys_dept set del_flag = '2' where dept_id = #{deptId}
+	</delete>
+
+</mapper> 
\ No newline at end of file
diff --git a/jcdm-system/src/main/resources/mapper/system/SysDictDataMapper.xml b/jcdm-system/src/main/resources/mapper/system/SysDictDataMapper.xml
new file mode 100644
index 0000000..5e090db
--- /dev/null
+++ b/jcdm-system/src/main/resources/mapper/system/SysDictDataMapper.xml
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.system.mapper.SysDictDataMapper">
+	
+	<resultMap type="SysDictData" id="SysDictDataResult">
+		<id     property="dictCode"   column="dict_code"   />
+		<result property="dictSort"   column="dict_sort"   />
+		<result property="dictLabel"  column="dict_label"  />
+		<result property="dictValue"  column="dict_value"  />
+		<result property="dictType"   column="dict_type"   />
+		<result property="cssClass"   column="css_class"   />
+		<result property="listClass"  column="list_class"  />
+		<result property="isDefault"  column="is_default"  />
+		<result property="status"     column="status"      />
+		<result property="createBy"   column="create_by"   />
+		<result property="createTime" column="create_time" />
+		<result property="updateBy"   column="update_by"   />
+		<result property="updateTime" column="update_time" />
+	</resultMap>
+	
+	<sql id="selectDictDataVo">
+        select dict_code, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark 
+		from sys_dict_data
+    </sql>
+
+	<select id="selectDictDataList" parameterType="SysDictData" resultMap="SysDictDataResult">
+	    <include refid="selectDictDataVo"/>
+		<where>
+		    <if test="dictType != null and dictType != ''">
+				AND dict_type = #{dictType}
+			</if>
+			<if test="dictLabel != null and dictLabel != ''">
+				AND dict_label like concat('%', #{dictLabel}, '%')
+			</if>
+			<if test="status != null and status != ''">
+				AND status = #{status}
+			</if>
+		</where>
+		order by dict_sort asc
+	</select>
+	
+	<select id="selectDictDataByType" parameterType="SysDictData" resultMap="SysDictDataResult">
+		<include refid="selectDictDataVo"/>
+		where status = '0' and dict_type = #{dictType} order by dict_sort asc
+	</select>
+	
+	<select id="selectDictLabel" resultType="String">
+		select dict_label from sys_dict_data
+		where dict_type = #{dictType} and dict_value = #{dictValue}
+	</select>
+	
+	<select id="selectDictDataById" parameterType="Long" resultMap="SysDictDataResult">
+		<include refid="selectDictDataVo"/>
+		where dict_code = #{dictCode}
+	</select>
+	
+	<select id="countDictDataByType" resultType="Integer">
+	    select count(1) from sys_dict_data where dict_type=#{dictType}  
+	</select>
+	
+	<delete id="deleteDictDataById" parameterType="Long">
+ 		delete from sys_dict_data where dict_code = #{dictCode}
+ 	</delete>
+ 	
+ 	<delete id="deleteDictDataByIds" parameterType="Long">
+ 		delete from sys_dict_data where dict_code in
+ 		<foreach collection="array" item="dictCode" open="(" separator="," close=")">
+ 			#{dictCode}
+        </foreach> 
+ 	</delete>
+	
+	<update id="updateDictData" parameterType="SysDictData">
+ 		update sys_dict_data
+ 		<set>
+ 			<if test="dictSort != null">dict_sort = #{dictSort},</if>
+ 			<if test="dictLabel != null and dictLabel != ''">dict_label = #{dictLabel},</if>
+ 			<if test="dictValue != null and dictValue != ''">dict_value = #{dictValue},</if>
+ 			<if test="dictType != null and dictType != ''">dict_type = #{dictType},</if>
+ 			<if test="cssClass != null">css_class = #{cssClass},</if>
+ 			<if test="listClass != null">list_class = #{listClass},</if>
+ 			<if test="isDefault != null and isDefault != ''">is_default = #{isDefault},</if>
+ 			<if test="status != null">status = #{status},</if>
+ 			<if test="remark != null">remark = #{remark},</if>
+ 			<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
+ 			update_time = getdate()
+ 		</set>
+ 		where dict_code = #{dictCode}
+	</update>
+	
+	<update id="updateDictDataType" parameterType="String">
+ 		update sys_dict_data set dict_type = #{newDictType} where dict_type = #{oldDictType}
+	</update>
+ 	
+ 	<insert id="insertDictData" parameterType="SysDictData">
+ 		insert into sys_dict_data(
+ 			<if test="dictSort != null">dict_sort,</if>
+ 			<if test="dictLabel != null and dictLabel != ''">dict_label,</if>
+ 			<if test="dictValue != null and dictValue != ''">dict_value,</if>
+ 			<if test="dictType != null and dictType != ''">dict_type,</if>
+ 			<if test="cssClass != null and cssClass != ''">css_class,</if>
+ 			<if test="listClass != null and listClass != ''">list_class,</if>
+ 			<if test="isDefault != null and isDefault != ''">is_default,</if>
+ 			<if test="status != null">status,</if>
+ 			<if test="remark != null and remark != ''">remark,</if>
+ 			<if test="createBy != null and createBy != ''">create_by,</if>
+ 			create_time
+ 		)values(
+ 		    <if test="dictSort != null">#{dictSort},</if>
+ 		    <if test="dictLabel != null and dictLabel != ''">#{dictLabel},</if>
+ 			<if test="dictValue != null and dictValue != ''">#{dictValue},</if>
+ 			<if test="dictType != null and dictType != ''">#{dictType},</if>
+ 			<if test="cssClass != null and cssClass != ''">#{cssClass},</if>
+ 			<if test="listClass != null and listClass != ''">#{listClass},</if>
+ 			<if test="isDefault != null and isDefault != ''">#{isDefault},</if>
+ 			<if test="status != null">#{status},</if>
+ 			<if test="remark != null and remark != ''">#{remark},</if>
+ 			<if test="createBy != null and createBy != ''">#{createBy},</if>
+ 			getdate()
+ 		)
+	</insert>
+	
+</mapper> 
\ No newline at end of file
diff --git a/jcdm-system/src/main/resources/mapper/system/SysDictTypeMapper.xml b/jcdm-system/src/main/resources/mapper/system/SysDictTypeMapper.xml
new file mode 100644
index 0000000..105072a
--- /dev/null
+++ b/jcdm-system/src/main/resources/mapper/system/SysDictTypeMapper.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+		PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+		"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.system.mapper.SysDictTypeMapper">
+
+	<resultMap type="SysDictType" id="SysDictTypeResult">
+		<id     property="dictId"     column="dict_id"     />
+		<result property="dictName"   column="dict_name"   />
+		<result property="dictType"   column="dict_type"   />
+		<result property="status"     column="status"      />
+		<result property="createBy"   column="create_by"   />
+		<result property="createTime" column="create_time" />
+		<result property="updateBy"   column="update_by"   />
+		<result property="updateTime" column="update_time" />
+	</resultMap>
+
+	<sql id="selectDictTypeVo">
+		select dict_id, dict_name, dict_type, status, create_by, create_time, remark
+		from sys_dict_type
+	</sql>
+
+	<select id="selectDictTypeList" parameterType="SysDictType" resultMap="SysDictTypeResult">
+		<include refid="selectDictTypeVo"/>
+		<where>
+			<if test="dictName != null and dictName != ''">
+				AND dict_name like concat('%', #{dictName}, '%')
+			</if>
+			<if test="status != null and status != ''">
+				AND status = #{status}
+			</if>
+			<if test="dictType != null and dictType != ''">
+				AND dict_type like concat('%', #{dictType}, '%')
+			</if>
+			<if test="params.beginTime != null and params.beginTime != ''"><!-- 寮�濮嬫椂闂存绱� -->
+				<!--				and <![CDATA[ create_time >= convert(datetime, #{params.beginTime}, 20)]]>-->
+				and datediff(d, create_time, #{params.beginTime}) <![CDATA[<=]]> 0
+			</if>
+			<if test="params.endTime != null and params.endTime != ''"><!-- 缁撴潫鏃堕棿妫�绱� -->
+				<!--				and <![CDATA[ create_time <= convert(datetime, #{params.endTime}, 20)]]>-->
+				and datediff(d, create_time, #{params.endTime}) <![CDATA[>=]]> 0
+			</if>
+		</where>
+	</select>
+
+	<select id="selectDictTypeAll" resultMap="SysDictTypeResult">
+		<include refid="selectDictTypeVo"/>
+	</select>
+
+	<select id="selectDictTypeById" parameterType="Long" resultMap="SysDictTypeResult">
+		<include refid="selectDictTypeVo"/>
+		where dict_id = #{dictId}
+	</select>
+
+	<select id="selectDictTypeByType" parameterType="String" resultMap="SysDictTypeResult">
+		<include refid="selectDictTypeVo"/>
+		where dict_type = #{dictType}
+	</select>
+
+	<select id="checkDictTypeUnique" parameterType="String" resultMap="SysDictTypeResult">
+		select top(1) dict_id, dict_name, dict_type, status, create_by, create_time, remark
+		from sys_dict_type
+		where dict_type = #{dictType}
+	</select>
+
+	<delete id="deleteDictTypeById" parameterType="Long">
+		delete from sys_dict_type where dict_id = #{dictId}
+	</delete>
+
+	<delete id="deleteDictTypeByIds" parameterType="Long">
+		delete from sys_dict_type where dict_id in
+		<foreach collection="array" item="dictId" open="(" separator="," close=")">
+			#{dictId}
+		</foreach>
+	</delete>
+
+	<update id="updateDictType" parameterType="SysDictType">
+		update sys_dict_type
+		<set>
+			<if test="dictName != null and dictName != ''">dict_name = #{dictName},</if>
+			<if test="dictType != null and dictType != ''">dict_type = #{dictType},</if>
+			<if test="status != null">status = #{status},</if>
+			<if test="remark != null">remark = #{remark},</if>
+			<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
+			update_time = getdate()
+		</set>
+		where dict_id = #{dictId}
+	</update>
+
+	<insert id="insertDictType" parameterType="SysDictType">
+		insert into sys_dict_type(
+		<if test="dictName != null and dictName != ''">dict_name,</if>
+		<if test="dictType != null and dictType != ''">dict_type,</if>
+		<if test="status != null">status,</if>
+		<if test="remark != null and remark != ''">remark,</if>
+		<if test="createBy != null and createBy != ''">create_by,</if>
+		create_time
+		)values(
+		<if test="dictName != null and dictName != ''">#{dictName},</if>
+		<if test="dictType != null and dictType != ''">#{dictType},</if>
+		<if test="status != null">#{status},</if>
+		<if test="remark != null and remark != ''">#{remark},</if>
+		<if test="createBy != null and createBy != ''">#{createBy},</if>
+		getdate()
+		)
+	</insert>
+
+</mapper> 
\ No newline at end of file
diff --git a/jcdm-system/src/main/resources/mapper/system/SysLogininforMapper.xml b/jcdm-system/src/main/resources/mapper/system/SysLogininforMapper.xml
new file mode 100644
index 0000000..05ad07f
--- /dev/null
+++ b/jcdm-system/src/main/resources/mapper/system/SysLogininforMapper.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+		PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+		"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.system.mapper.SysLogininforMapper">
+
+	<resultMap type="SysLogininfor" id="SysLogininforResult">
+		<id     property="infoId"        column="info_id"           />
+		<result property="userName"      column="user_name"         />
+		<result property="status"        column="status"            />
+		<result property="ipaddr"        column="ipaddr"            />
+		<result property="loginLocation" column="login_location"    />
+		<result property="browser"       column="browser"           />
+		<result property="os"            column="os"                />
+		<result property="msg"           column="msg"               />
+		<result property="loginTime"     column="login_time"        />
+	</resultMap>
+
+	<insert id="insertLogininfor" parameterType="SysLogininfor">
+		insert into sys_logininfor (user_name, status, ipaddr, login_location, browser, os, msg, login_time)
+		values (#{userName}, #{status}, #{ipaddr}, #{loginLocation}, #{browser}, #{os}, #{msg}, getdate())
+	</insert>
+
+	<select id="selectLogininforList" parameterType="SysLogininfor" resultMap="SysLogininforResult">
+		select info_id, user_name, ipaddr, login_location, browser, os, status, msg, login_time from sys_logininfor
+		<where>
+			<if test="ipaddr != null and ipaddr != ''">
+				AND ipaddr like concat('%', #{ipaddr}, '%')
+			</if>
+			<if test="status != null and status != ''">
+				AND status = #{status}
+			</if>
+			<if test="userName != null and userName != ''">
+				AND user_name like concat('%', #{userName}, '%')
+			</if>
+			<if test="params.beginTime != null and params.beginTime != ''"><!-- 寮�濮嬫椂闂存绱� -->
+				<!--				and <![CDATA[ login_time >= convert(datetime, #{params.beginTime}, 20)]]>-->
+				and datediff(d, login_time, #{params.beginTime}) <![CDATA[<=]]> 0
+			</if>
+			<if test="params.endTime != null and params.endTime != ''"><!-- 缁撴潫鏃堕棿妫�绱� -->
+				<!--				and <![CDATA[ login_time <= convert(datetime, #{params.endTime}, 20)]]>-->
+				and datediff(d, login_time, #{params.endTime}) <![CDATA[>=]]> 0
+			</if>
+		</where>
+		order by info_id desc
+	</select>
+
+	<delete id="deleteLogininforByIds" parameterType="Long">
+		delete from sys_logininfor where info_id in
+		<foreach collection="array" item="infoId" open="(" separator="," close=")">
+			#{infoId}
+		</foreach>
+	</delete>
+
+	<update id="cleanLogininfor">
+		truncate table sys_logininfor
+	</update>
+
+</mapper> 
\ No newline at end of file
diff --git a/jcdm-system/src/main/resources/mapper/system/SysMenuMapper.xml b/jcdm-system/src/main/resources/mapper/system/SysMenuMapper.xml
new file mode 100644
index 0000000..31c846e
--- /dev/null
+++ b/jcdm-system/src/main/resources/mapper/system/SysMenuMapper.xml
@@ -0,0 +1,203 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+		PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+		"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.system.mapper.SysMenuMapper">
+
+	<resultMap type="SysMenu" id="SysMenuResult">
+		<id     property="menuId"         column="menu_id"        />
+		<result property="menuName"       column="menu_name"      />
+		<result property="parentName"     column="parent_name"    />
+		<result property="parentId"       column="parent_id"      />
+		<result property="orderNum"       column="order_num"      />
+		<result property="path"           column="path"           />
+		<result property="component"      column="component"      />
+		<result property="query"          column="query"          />
+		<result property="isFrame"        column="is_frame"       />
+		<result property="isCache"        column="is_cache"       />
+		<result property="menuType"       column="menu_type"      />
+		<result property="visible"        column="visible"        />
+		<result property="status"         column="status"         />
+		<result property="perms"          column="perms"          />
+		<result property="icon"           column="icon"           />
+		<result property="createBy"       column="create_by"      />
+		<result property="createTime"     column="create_time"    />
+		<result property="updateTime"     column="update_time"    />
+		<result property="updateBy"       column="update_by"      />
+		<result property="remark"         column="remark"         />
+	</resultMap>
+
+	<sql id="selectMenuVo">
+		select menu_id, menu_name, parent_id, order_num, path, component, query, is_frame, is_cache, menu_type, visible, status, isnull(perms,'') as perms, icon, create_time
+		from sys_menu
+	</sql>
+
+	<select id="selectMenuList" parameterType="SysMenu" resultMap="SysMenuResult">
+		<include refid="selectMenuVo"/>
+		<where>
+			<if test="menuName != null and menuName != ''">
+				AND menu_name like concat('%', #{menuName}, '%')
+			</if>
+			<if test="visible != null and visible != ''">
+				AND visible = #{visible}
+			</if>
+			<if test="status != null and status != ''">
+				AND status = #{status}
+			</if>
+		</where>
+		order by parent_id, order_num
+	</select>
+
+	<select id="selectMenuTreeAll" resultMap="SysMenuResult">
+		select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.query, m.visible, m.status, isnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
+		from sys_menu m where m.menu_type in ('M', 'C') and m.status = 0
+		order by m.parent_id, m.order_num
+	</select>
+
+	<select id="selectMenuListByUserId" parameterType="SysMenu" resultMap="SysMenuResult">
+		select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.query, m.visible, m.status, isnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
+		from sys_menu m
+		left join sys_role_menu rm on m.menu_id = rm.menu_id
+		left join sys_user_role ur on rm.role_id = ur.role_id
+		left join sys_role ro on ur.role_id = ro.role_id
+		where ur.user_id = #{params.userId}
+		<if test="menuName != null and menuName != ''">
+			AND m.menu_name like concat('%', #{menuName}, '%')
+		</if>
+		<if test="visible != null and visible != ''">
+			AND m.visible = #{visible}
+		</if>
+		<if test="status != null and status != ''">
+			AND m.status = #{status}
+		</if>
+		order by m.parent_id, m.order_num
+	</select>
+
+	<select id="selectMenuTreeByUserId" parameterType="Long" resultMap="SysMenuResult">
+		select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.query, m.visible, m.status, isnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
+		from sys_menu m
+				 left join sys_role_menu rm on m.menu_id = rm.menu_id
+				 left join sys_user_role ur on rm.role_id = ur.role_id
+				 left join sys_role ro on ur.role_id = ro.role_id
+				 left join sys_user u on ur.user_id = u.user_id
+		where u.user_id = #{userId} and m.menu_type in ('M', 'C') and m.status = 0  AND ro.status = 0
+		order by m.parent_id, m.order_num
+	</select>
+
+	<select id="selectMenuListByRoleId" resultType="Long">
+		select m.menu_id
+		from sys_menu m
+		left join sys_role_menu rm on m.menu_id = rm.menu_id
+		where rm.role_id = #{roleId}
+		<if test="menuCheckStrictly">
+			and m.menu_id not in (select m.parent_id from sys_menu m inner join sys_role_menu rm on m.menu_id = rm.menu_id and rm.role_id = #{roleId})
+		</if>
+		order by m.parent_id, m.order_num
+	</select>
+
+	<select id="selectMenuPerms" resultType="String">
+		select distinct m.perms
+		from sys_menu m
+				 left join sys_role_menu rm on m.menu_id = rm.menu_id
+				 left join sys_user_role ur on rm.role_id = ur.role_id
+	</select>
+
+	<select id="selectMenuPermsByUserId" parameterType="Long" resultType="String">
+		select distinct m.perms
+		from sys_menu m
+				 left join sys_role_menu rm on m.menu_id = rm.menu_id
+				 left join sys_user_role ur on rm.role_id = ur.role_id
+				 left join sys_role r on r.role_id = ur.role_id
+		where m.status = '0' and r.status = '0' and ur.user_id = #{userId}
+	</select>
+
+	<select id="selectMenuPermsByRoleId" parameterType="Long" resultType="String">
+		select distinct m.perms
+		from sys_menu m
+				 left join sys_role_menu rm on m.menu_id = rm.menu_id
+		where m.status = '0' and rm.role_id = #{roleId}
+	</select>
+
+	<select id="selectMenuById" parameterType="Long" resultMap="SysMenuResult">
+		<include refid="selectMenuVo"/>
+		where menu_id = #{menuId}
+	</select>
+
+	<select id="hasChildByMenuId" resultType="Integer">
+		select count(1) from sys_menu where parent_id = #{menuId}
+	</select>
+
+	<select id="checkMenuNameUnique" parameterType="SysMenu" resultMap="SysMenuResult">
+		select top(1) menu_id, menu_name, parent_id, order_num, path, component, query, is_frame, is_cache, menu_type, visible, status, isnull(perms,'') as perms, icon, create_time
+		from sys_menu
+		where menu_name=#{menuName} and parent_id = #{parentId}
+	</select>
+
+	<update id="updateMenu" parameterType="SysMenu">
+		update sys_menu
+		<set>
+			<if test="menuName != null and menuName != ''">menu_name = #{menuName},</if>
+			<if test="parentId != null">parent_id = #{parentId},</if>
+			<if test="orderNum != null">order_num = #{orderNum},</if>
+			<if test="path != null and path != ''">path = #{path},</if>
+			<if test="component != null">component = #{component},</if>
+			<if test="query != null"> query = #{query},</if>
+			<if test="isFrame != null and isFrame != ''">is_frame = #{isFrame},</if>
+			<if test="isCache != null and isCache != ''">is_cache = #{isCache},</if>
+			<if test="menuType != null and menuType != ''">menu_type = #{menuType},</if>
+			<if test="visible != null">visible = #{visible},</if>
+			<if test="status != null">status = #{status},</if>
+			<if test="perms !=null">perms = #{perms},</if>
+			<if test="icon !=null and icon != ''">icon = #{icon},</if>
+			<if test="remark != null and remark != ''">remark = #{remark},</if>
+			<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
+			update_time = getdate()
+		</set>
+		where menu_id = #{menuId}
+	</update>
+
+	<insert id="insertMenu" parameterType="SysMenu">
+		insert into sys_menu(
+		<if test="menuId != null and menuId != 0">menu_id,</if>
+		<if test="parentId != null and parentId != 0">parent_id,</if>
+		<if test="menuName != null and menuName != ''">menu_name,</if>
+		<if test="orderNum != null">order_num,</if>
+		<if test="path != null and path != ''">path,</if>
+		<if test="component != null and component != ''">component,</if>
+		<if test="query != null and query != ''">query,</if>
+		<if test="isFrame != null and isFrame != ''">is_frame,</if>
+		<if test="isCache != null and isCache != ''">is_cache,</if>
+		<if test="menuType != null and menuType != ''">menu_type,</if>
+		<if test="visible != null">visible,</if>
+		<if test="status != null">status,</if>
+		<if test="perms !=null and perms != ''">perms,</if>
+		<if test="icon != null and icon != ''">icon,</if>
+		<if test="remark != null and remark != ''">remark,</if>
+		<if test="createBy != null and createBy != ''">create_by,</if>
+		create_time
+		)values(
+		<if test="menuId != null and menuId != 0">#{menuId},</if>
+		<if test="parentId != null and parentId != 0">#{parentId},</if>
+		<if test="menuName != null and menuName != ''">#{menuName},</if>
+		<if test="orderNum != null">#{orderNum},</if>
+		<if test="path != null and path != ''">#{path},</if>
+		<if test="component != null and component != ''">#{component},</if>
+		<if test="query != null and query != ''">#{query},</if>
+		<if test="isFrame != null and isFrame != ''">#{isFrame},</if>
+		<if test="isCache != null and isCache != ''">#{isCache},</if>
+		<if test="menuType != null and menuType != ''">#{menuType},</if>
+		<if test="visible != null">#{visible},</if>
+		<if test="status != null">#{status},</if>
+		<if test="perms !=null and perms != ''">#{perms},</if>
+		<if test="icon != null and icon != ''">#{icon},</if>
+		<if test="remark != null and remark != ''">#{remark},</if>
+		<if test="createBy != null and createBy != ''">#{createBy},</if>
+		getdate()
+		)
+	</insert>
+
+	<delete id="deleteMenuById" parameterType="Long">
+		delete from sys_menu where menu_id = #{menuId}
+	</delete>
+
+</mapper> 
\ No newline at end of file
diff --git a/jcdm-system/src/main/resources/mapper/system/SysNoticeMapper.xml b/jcdm-system/src/main/resources/mapper/system/SysNoticeMapper.xml
new file mode 100644
index 0000000..4f1bff4
--- /dev/null
+++ b/jcdm-system/src/main/resources/mapper/system/SysNoticeMapper.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.system.mapper.SysNoticeMapper">
+    
+    <resultMap type="SysNotice" id="SysNoticeResult">
+        <result property="noticeId"       column="notice_id"       />
+        <result property="noticeTitle"    column="notice_title"    />
+        <result property="noticeType"     column="notice_type"     />
+        <result property="noticeContent"  column="notice_content"  />
+        <result property="status"         column="status"          />
+        <result property="createBy"       column="create_by"       />
+        <result property="createTime"     column="create_time"     />
+        <result property="updateBy"       column="update_by"       />
+        <result property="updateTime"     column="update_time"     />
+        <result property="remark"         column="remark"          />
+    </resultMap>
+    
+    <sql id="selectNoticeVo">
+        select notice_id, notice_title, notice_type, cast(notice_content as char) as notice_content, status, create_by, create_time, update_by, update_time, remark 
+		from sys_notice
+    </sql>
+    
+    <select id="selectNoticeById" parameterType="Long" resultMap="SysNoticeResult">
+        <include refid="selectNoticeVo"/>
+        where notice_id = #{noticeId}
+    </select>
+    
+    <select id="selectNoticeList" parameterType="SysNotice" resultMap="SysNoticeResult">
+        <include refid="selectNoticeVo"/>
+        <where>
+			<if test="noticeTitle != null and noticeTitle != ''">
+				AND notice_title like concat('%', #{noticeTitle}, '%')
+			</if>
+			<if test="noticeType != null and noticeType != ''">
+				AND notice_type = #{noticeType}
+			</if>
+			<if test="createBy != null and createBy != ''">
+				AND create_by like concat('%', #{createBy}, '%')
+			</if>
+		</where>
+    </select>
+    
+    <insert id="insertNotice" parameterType="SysNotice">
+        insert into sys_notice (
+			<if test="noticeTitle != null and noticeTitle != '' ">notice_title, </if>
+			<if test="noticeType != null and noticeType != '' ">notice_type, </if>
+			<if test="noticeContent != null and noticeContent != '' ">notice_content, </if>
+			<if test="status != null and status != '' ">status, </if>
+			<if test="remark != null and remark != ''">remark,</if>
+ 			<if test="createBy != null and createBy != ''">create_by,</if>
+ 			create_time
+ 		)values(
+			<if test="noticeTitle != null and noticeTitle != ''">#{noticeTitle}, </if>
+			<if test="noticeType != null and noticeType != ''">#{noticeType}, </if>
+			<if test="noticeContent != null and noticeContent != ''">#{noticeContent}, </if>
+			<if test="status != null and status != ''">#{status}, </if>
+			<if test="remark != null and remark != ''">#{remark},</if>
+ 			<if test="createBy != null and createBy != ''">#{createBy},</if>
+ 			getdate()
+		)
+    </insert>
+	 
+    <update id="updateNotice" parameterType="SysNotice">
+        update sys_notice 
+        <set>
+            <if test="noticeTitle != null and noticeTitle != ''">notice_title = #{noticeTitle}, </if>
+            <if test="noticeType != null and noticeType != ''">notice_type = #{noticeType}, </if>
+            <if test="noticeContent != null">notice_content = #{noticeContent}, </if>
+            <if test="status != null and status != ''">status = #{status}, </if>
+            <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
+ 			update_time = getdate()
+        </set>
+        where notice_id = #{noticeId}
+    </update>
+	
+    <delete id="deleteNoticeById" parameterType="Long">
+        delete from sys_notice where notice_id = #{noticeId}
+    </delete>
+    
+    <delete id="deleteNoticeByIds" parameterType="Long">
+        delete from sys_notice where notice_id in 
+        <foreach item="noticeId" collection="array" open="(" separator="," close=")">
+            #{noticeId}
+        </foreach>
+    </delete>
+    
+</mapper>
\ No newline at end of file
diff --git a/jcdm-system/src/main/resources/mapper/system/SysOperLogMapper.xml b/jcdm-system/src/main/resources/mapper/system/SysOperLogMapper.xml
new file mode 100644
index 0000000..6144266
--- /dev/null
+++ b/jcdm-system/src/main/resources/mapper/system/SysOperLogMapper.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.system.mapper.SysOperLogMapper">
+
+	<resultMap type="SysOperLog" id="SysOperLogResult">
+		<id     property="operId"         column="oper_id"        />
+		<result property="title"          column="title"          />
+		<result property="businessType"   column="business_type"  />
+		<result property="method"         column="method"         />
+		<result property="requestMethod"  column="request_method" />
+		<result property="operatorType"   column="operator_type"  />
+		<result property="operName"       column="oper_name"      />
+		<result property="deptName"       column="dept_name"      />
+		<result property="operUrl"        column="oper_url"       />
+		<result property="operIp"         column="oper_ip"        />
+		<result property="operLocation"   column="oper_location"  />
+		<result property="operParam"      column="oper_param"     />
+		<result property="jsonResult"     column="json_result"    />
+		<result property="status"         column="status"         />
+		<result property="errorMsg"       column="error_msg"      />
+		<result property="operTime"       column="oper_time"      />
+		<result property="costTime"       column="cost_time"      />
+	</resultMap>
+
+	<sql id="selectOperLogVo">
+        select oper_id, title, business_type, method, request_method, operator_type, oper_name, dept_name, oper_url, oper_ip, oper_location, oper_param, json_result, status, error_msg, oper_time, cost_time
+        from sys_oper_log
+    </sql>
+    
+	<insert id="insertOperlog" parameterType="SysOperLog">
+		insert into sys_oper_log(title, business_type, method, request_method, operator_type, oper_name, dept_name, oper_url, oper_ip, oper_location, oper_param, json_result, status, error_msg, cost_time, oper_time)
+        values (#{title}, #{businessType}, #{method}, #{requestMethod}, #{operatorType}, #{operName}, #{deptName}, #{operUrl}, #{operIp}, #{operLocation}, #{operParam}, #{jsonResult}, #{status}, #{errorMsg}, #{costTime}, getdate())
+	</insert>
+	
+	<select id="selectOperLogList" parameterType="SysOperLog" resultMap="SysOperLogResult">
+		<include refid="selectOperLogVo"/>
+		<where>
+			<if test="operIp != null and operIp != ''">
+				AND oper_ip like concat('%', #{operIp}, '%')
+			</if>
+			<if test="title != null and title != ''">
+				AND title like concat('%', #{title}, '%')
+			</if>
+			<if test="businessType != null">
+				AND business_type = #{businessType}
+			</if>
+			<if test="businessTypes != null and businessTypes.length > 0">
+			    AND business_type in
+			    <foreach collection="businessTypes" item="businessType" open="(" separator="," close=")">
+		 			#{businessType}
+		        </foreach> 
+			</if>
+			<if test="status != null">
+				AND status = #{status}
+			</if>
+			<if test="operName != null and operName != ''">
+				AND oper_name like concat('%', #{operName}, '%')
+			</if>
+			<if test="params.beginTime != null and params.beginTime != ''"><!-- 寮�濮嬫椂闂存绱� -->
+				AND oper_time &gt;= #{params.beginTime}
+			</if>
+			<if test="params.endTime != null and params.endTime != ''"><!-- 缁撴潫鏃堕棿妫�绱� -->
+				AND oper_time &lt;= #{params.endTime}
+			</if>
+		</where>
+		order by oper_id desc
+	</select>
+	
+	<delete id="deleteOperLogByIds" parameterType="Long">
+ 		delete from sys_oper_log where oper_id in
+ 		<foreach collection="array" item="operId" open="(" separator="," close=")">
+ 			#{operId}
+        </foreach> 
+ 	</delete>
+ 	
+ 	<select id="selectOperLogById" parameterType="Long" resultMap="SysOperLogResult">
+		<include refid="selectOperLogVo"/>
+		where oper_id = #{operId}
+	</select>
+	
+	<update id="cleanOperLog">
+        truncate table sys_oper_log
+    </update>
+
+</mapper> 
\ No newline at end of file
diff --git a/jcdm-system/src/main/resources/mapper/system/SysPostMapper.xml b/jcdm-system/src/main/resources/mapper/system/SysPostMapper.xml
new file mode 100644
index 0000000..c1379ec
--- /dev/null
+++ b/jcdm-system/src/main/resources/mapper/system/SysPostMapper.xml
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+		PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+		"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.system.mapper.SysPostMapper">
+
+	<resultMap type="SysPost" id="SysPostResult">
+		<id     property="postId"        column="post_id"       />
+		<result property="postCode"      column="post_code"     />
+		<result property="postName"      column="post_name"     />
+		<result property="postSort"      column="post_sort"     />
+		<result property="status"        column="status"        />
+		<result property="createBy"      column="create_by"     />
+		<result property="createTime"    column="create_time"   />
+		<result property="updateBy"      column="update_by"     />
+		<result property="updateTime"    column="update_time"   />
+		<result property="remark"        column="remark"        />
+	</resultMap>
+
+	<sql id="selectPostVo">
+		select post_id, post_code, post_name, post_sort, status, create_by, create_time, remark
+		from sys_post
+	</sql>
+
+	<select id="selectPostList" parameterType="SysPost" resultMap="SysPostResult">
+		<include refid="selectPostVo"/>
+		<where>
+			<if test="postCode != null and postCode != ''">
+				AND post_code like concat('%', #{postCode}, '%')
+			</if>
+			<if test="status != null and status != ''">
+				AND status = #{status}
+			</if>
+			<if test="postName != null and postName != ''">
+				AND post_name like concat('%', #{postName}, '%')
+			</if>
+		</where>
+	</select>
+
+	<select id="selectPostAll" resultMap="SysPostResult">
+		<include refid="selectPostVo"/>
+	</select>
+
+	<select id="selectPostById" parameterType="Long" resultMap="SysPostResult">
+		<include refid="selectPostVo"/>
+		where post_id = #{postId}
+	</select>
+
+	<select id="selectPostListByUserId" parameterType="Long" resultType="Long">
+		select p.post_id
+		from sys_post p
+				 left join sys_user_post up on up.post_id = p.post_id
+				 left join sys_user u on u.user_id = up.user_id
+		where u.user_id = #{userId}
+	</select>
+
+	<select id="selectPostsByUserName" parameterType="String" resultMap="SysPostResult">
+		select p.post_id, p.post_name, p.post_code
+		from sys_post p
+				 left join sys_user_post up on up.post_id = p.post_id
+				 left join sys_user u on u.user_id = up.user_id
+		where u.user_name = #{userName}
+	</select>
+
+	<select id="checkPostNameUnique" parameterType="String" resultMap="SysPostResult">
+		select top(1) post_id, post_code, post_name, post_sort, status, create_by, create_time, remark
+		from sys_post
+		where post_name=#{postName}
+	</select>
+
+	<select id="checkPostCodeUnique" parameterType="String" resultMap="SysPostResult">
+		select top(1) post_id, post_code, post_name, post_sort, status, create_by, create_time, remark
+		from sys_post
+		where post_code=#{postCode}
+	</select>
+
+	<update id="updatePost" parameterType="SysPost">
+		update sys_post
+		<set>
+			<if test="postCode != null and postCode != ''">post_code = #{postCode},</if>
+			<if test="postName != null and postName != ''">post_name = #{postName},</if>
+			<if test="postSort != null">post_sort = #{postSort},</if>
+			<if test="status != null and status != ''">status = #{status},</if>
+			<if test="remark != null">remark = #{remark},</if>
+			<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
+			update_time = getdate()
+		</set>
+		where post_id = #{postId}
+	</update>
+
+	<insert id="insertPost" parameterType="SysPost" useGeneratedKeys="true" keyProperty="postId">
+		insert into sys_post(
+		<if test="postId != null and postId != 0">post_id,</if>
+		<if test="postCode != null and postCode != ''">post_code,</if>
+		<if test="postName != null and postName != ''">post_name,</if>
+		<if test="postSort != null">post_sort,</if>
+		<if test="status != null and status != ''">status,</if>
+		<if test="remark != null and remark != ''">remark,</if>
+		<if test="createBy != null and createBy != ''">create_by,</if>
+		create_time
+		)values(
+		<if test="postId != null and postId != 0">#{postId},</if>
+		<if test="postCode != null and postCode != ''">#{postCode},</if>
+		<if test="postName != null and postName != ''">#{postName},</if>
+		<if test="postSort != null">#{postSort},</if>
+		<if test="status != null and status != ''">#{status},</if>
+		<if test="remark != null and remark != ''">#{remark},</if>
+		<if test="createBy != null and createBy != ''">#{createBy},</if>
+		getdate()
+		)
+	</insert>
+
+	<delete id="deletePostById" parameterType="Long">
+		delete from sys_post where post_id = #{postId}
+	</delete>
+
+	<delete id="deletePostByIds" parameterType="Long">
+		delete from sys_post where post_id in
+		<foreach collection="array" item="postId" open="(" separator="," close=")">
+			#{postId}
+		</foreach>
+	</delete>
+
+</mapper> 
\ No newline at end of file
diff --git a/jcdm-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml b/jcdm-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml
new file mode 100644
index 0000000..d3b8ac4
--- /dev/null
+++ b/jcdm-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.system.mapper.SysRoleDeptMapper">
+
+	<resultMap type="SysRoleDept" id="SysRoleDeptResult">
+		<result property="roleId"     column="role_id"      />
+		<result property="deptId"     column="dept_id"      />
+	</resultMap>
+
+	<delete id="deleteRoleDeptByRoleId" parameterType="Long">
+		delete from sys_role_dept where role_id=#{roleId}
+	</delete>
+	
+	<select id="selectCountRoleDeptByDeptId" resultType="Integer">
+	    select count(1) from sys_role_dept where dept_id=#{deptId}
+	</select>
+	
+	<delete id="deleteRoleDept" parameterType="Long">
+ 		delete from sys_role_dept where role_id in
+ 		<foreach collection="array" item="roleId" open="(" separator="," close=")">
+ 			#{roleId}
+        </foreach> 
+ 	</delete>
+	
+	<insert id="batchRoleDept">
+		insert into sys_role_dept(role_id, dept_id) values
+		<foreach item="item" index="index" collection="list" separator=",">
+			(#{item.roleId},#{item.deptId})
+		</foreach>
+	</insert>
+	
+</mapper> 
\ No newline at end of file
diff --git a/jcdm-system/src/main/resources/mapper/system/SysRoleMapper.xml b/jcdm-system/src/main/resources/mapper/system/SysRoleMapper.xml
new file mode 100644
index 0000000..c07f9a3
--- /dev/null
+++ b/jcdm-system/src/main/resources/mapper/system/SysRoleMapper.xml
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.system.mapper.SysRoleMapper">
+
+	<resultMap type="SysRole" id="SysRoleResult">
+		<id     property="roleId"             column="role_id"               />
+		<result property="roleName"           column="role_name"             />
+		<result property="roleKey"            column="role_key"              />
+		<result property="roleSort"           column="role_sort"             />
+		<result property="dataScope"          column="data_scope"            />
+		<result property="menuCheckStrictly"  column="menu_check_strictly"   />
+		<result property="deptCheckStrictly"  column="dept_check_strictly"   />
+		<result property="status"             column="status"                />
+		<result property="delFlag"            column="del_flag"              />
+		<result property="createBy"           column="create_by"             />
+		<result property="createTime"         column="create_time"           />
+		<result property="updateBy"           column="update_by"             />
+		<result property="updateTime"         column="update_time"           />
+		<result property="remark"             column="remark"                />
+	</resultMap>
+	
+	<sql id="selectRoleVo">
+	    select distinct r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.menu_check_strictly, r.dept_check_strictly,
+            r.status, r.del_flag, r.create_time, r.remark 
+        from sys_role r
+	        left join sys_user_role ur on ur.role_id = r.role_id
+	        left join sys_user u on u.user_id = ur.user_id
+	        left join sys_dept d on u.dept_id = d.dept_id
+    </sql>
+    
+    <select id="selectRoleList" parameterType="SysRole" resultMap="SysRoleResult">
+		<include refid="selectRoleVo"/>
+		where r.del_flag = '0'
+		<if test="roleId != null and roleId != 0">
+			AND r.role_id = #{roleId}
+		</if>
+		<if test="roleName != null and roleName != ''">
+			AND r.role_name like concat('%', #{roleName}, '%')
+		</if>
+		<if test="status != null and status != ''">
+			AND r.status = #{status}
+		</if>
+		<if test="roleKey != null and roleKey != ''">
+			AND r.role_key like concat('%', #{roleKey}, '%')
+		</if>
+		<if test="params.beginTime != null and params.beginTime != ''"><!-- 寮�濮嬫椂闂存绱� -->
+			and date_format(r.create_time,'%y%m%d') &gt;= date_format(#{params.beginTime},'%y%m%d')
+		</if>
+		<if test="params.endTime != null and params.endTime != ''"><!-- 缁撴潫鏃堕棿妫�绱� -->
+			and date_format(r.create_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
+		</if>
+		<!-- 鏁版嵁鑼冨洿杩囨护 -->
+		${params.dataScope}
+		order by r.role_sort
+	</select>
+    
+	<select id="selectRolePermissionByUserId" parameterType="Long" resultMap="SysRoleResult">
+		<include refid="selectRoleVo"/>
+		WHERE r.del_flag = '0' and ur.user_id = #{userId}
+	</select>
+	
+	<select id="selectRoleAll" resultMap="SysRoleResult">
+		<include refid="selectRoleVo"/>
+	</select>
+	
+	<select id="selectRoleListByUserId" parameterType="Long" resultType="Long">
+		select r.role_id
+        from sys_role r
+	        left join sys_user_role ur on ur.role_id = r.role_id
+	        left join sys_user u on u.user_id = ur.user_id
+	    where u.user_id = #{userId}
+	</select>
+	
+	<select id="selectRoleById" parameterType="Long" resultMap="SysRoleResult">
+		<include refid="selectRoleVo"/>
+		where r.role_id = #{roleId}
+	</select>
+	
+	<select id="selectRolesByUserName" parameterType="String" resultMap="SysRoleResult">
+		<include refid="selectRoleVo"/>
+		WHERE r.del_flag = '0' and u.user_name = #{userName}
+	</select>
+	
+	<select id="checkRoleNameUnique" parameterType="String" resultMap="SysRoleResult">
+<!--		<include refid="selectRoleVo"/>-->
+<!--		 where r.role_name=#{roleName} and r.del_flag = '0' limit 1-->
+		select distinct top(1) r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.menu_check_strictly, r.dept_check_strictly,
+		r.status, r.del_flag, r.create_time, r.remark
+		from sys_role r
+		left join sys_user_role ur on ur.role_id = r.role_id
+		left join sys_user u on u.user_id = ur.user_id
+		left join sys_dept d on u.dept_id = d.dept_id
+		where r.role_name=#{roleName} and r.del_flag = '0'
+	</select>
+	
+	<select id="checkRoleKeyUnique" parameterType="String" resultMap="SysRoleResult">
+<!--		<include refid="selectRoleVo"/>-->
+<!--		 where r.role_key=#{roleKey} and r.del_flag = '0' limit 1-->
+		select distinct top(1) r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.menu_check_strictly, r.dept_check_strictly,
+		r.status, r.del_flag, r.create_time, r.remark
+		from sys_role r
+		left join sys_user_role ur on ur.role_id = r.role_id
+		left join sys_user u on u.user_id = ur.user_id
+		left join sys_dept d on u.dept_id = d.dept_id
+		where r.role_key=#{roleKey} and r.del_flag = '0'
+	</select>
+	
+ 	<insert id="insertRole" parameterType="SysRole" useGeneratedKeys="true" keyProperty="roleId">
+ 		insert into sys_role(
+ 			<if test="roleId != null and roleId != 0">role_id,</if>
+ 			<if test="roleName != null and roleName != ''">role_name,</if>
+ 			<if test="roleKey != null and roleKey != ''">role_key,</if>
+ 			<if test="roleSort != null">role_sort,</if>
+ 			<if test="dataScope != null and dataScope != ''">data_scope,</if>
+ 			<if test="menuCheckStrictly != null">menu_check_strictly,</if>
+ 			<if test="deptCheckStrictly != null">dept_check_strictly,</if>
+ 			<if test="status != null and status != ''">status,</if>
+ 			<if test="remark != null and remark != ''">remark,</if>
+ 			<if test="createBy != null and createBy != ''">create_by,</if>
+ 			create_time
+ 		)values(
+ 			<if test="roleId != null and roleId != 0">#{roleId},</if>
+ 			<if test="roleName != null and roleName != ''">#{roleName},</if>
+ 			<if test="roleKey != null and roleKey != ''">#{roleKey},</if>
+ 			<if test="roleSort != null">#{roleSort},</if>
+ 			<if test="dataScope != null and dataScope != ''">#{dataScope},</if>
+ 			<if test="menuCheckStrictly != null">#{menuCheckStrictly},</if>
+ 			<if test="deptCheckStrictly != null">#{deptCheckStrictly},</if>
+ 			<if test="status != null and status != ''">#{status},</if>
+ 			<if test="remark != null and remark != ''">#{remark},</if>
+ 			<if test="createBy != null and createBy != ''">#{createBy},</if>
+ 			getdate()
+ 		)
+	</insert>
+	
+	<update id="updateRole" parameterType="SysRole">
+ 		update sys_role
+ 		<set>
+ 			<if test="roleName != null and roleName != ''">role_name = #{roleName},</if>
+ 			<if test="roleKey != null and roleKey != ''">role_key = #{roleKey},</if>
+ 			<if test="roleSort != null">role_sort = #{roleSort},</if>
+ 			<if test="dataScope != null and dataScope != ''">data_scope = #{dataScope},</if>
+ 			<if test="menuCheckStrictly != null">menu_check_strictly = #{menuCheckStrictly},</if>
+ 			<if test="deptCheckStrictly != null">dept_check_strictly = #{deptCheckStrictly},</if>
+ 			<if test="status != null and status != ''">status = #{status},</if>
+ 			<if test="remark != null">remark = #{remark},</if>
+ 			<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
+ 			update_time = getdate()
+ 		</set>
+ 		where role_id = #{roleId}
+	</update>
+	
+	<delete id="deleteRoleById" parameterType="Long">
+ 		update sys_role set del_flag = '2' where role_id = #{roleId}
+ 	</delete>
+ 	
+ 	<delete id="deleteRoleByIds" parameterType="Long">
+ 	    update sys_role set del_flag = '2' where role_id in
+ 		<foreach collection="array" item="roleId" open="(" separator="," close=")">
+ 			#{roleId}
+        </foreach> 
+ 	</delete>
+ 	
+</mapper> 
\ No newline at end of file
diff --git a/jcdm-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml b/jcdm-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml
new file mode 100644
index 0000000..725aa56
--- /dev/null
+++ b/jcdm-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.system.mapper.SysRoleMenuMapper">
+
+	<resultMap type="SysRoleMenu" id="SysRoleMenuResult">
+		<result property="roleId"     column="role_id"      />
+		<result property="menuId"     column="menu_id"      />
+	</resultMap>
+	
+	<select id="checkMenuExistRole" resultType="Integer">
+	    select count(1) from sys_role_menu where menu_id = #{menuId}
+	</select>
+
+	<delete id="deleteRoleMenuByRoleId" parameterType="Long">
+		delete from sys_role_menu where role_id=#{roleId}
+	</delete>
+	
+	<delete id="deleteRoleMenu" parameterType="Long">
+ 		delete from sys_role_menu where role_id in
+ 		<foreach collection="array" item="roleId" open="(" separator="," close=")">
+ 			#{roleId}
+        </foreach> 
+ 	</delete>
+	
+	<insert id="batchRoleMenu">
+		insert into sys_role_menu(role_id, menu_id) values
+		<foreach item="item" index="index" collection="list" separator=",">
+			(#{item.roleId},#{item.menuId})
+		</foreach>
+	</insert>
+	
+</mapper> 
\ No newline at end of file
diff --git a/jcdm-system/src/main/resources/mapper/system/SysUserMapper.xml b/jcdm-system/src/main/resources/mapper/system/SysUserMapper.xml
new file mode 100644
index 0000000..607972a
--- /dev/null
+++ b/jcdm-system/src/main/resources/mapper/system/SysUserMapper.xml
@@ -0,0 +1,223 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+		PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+		"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.system.mapper.SysUserMapper">
+
+	<resultMap type="SysUser" id="SysUserResult">
+		<id     property="userId"       column="user_id"      />
+		<result property="deptId"       column="dept_id"      />
+		<result property="userName"     column="user_name"    />
+		<result property="nickName"     column="nick_name"    />
+		<result property="email"        column="email"        />
+		<result property="phonenumber"  column="phonenumber"  />
+		<result property="sex"          column="sex"          />
+		<result property="avatar"       column="avatar"       />
+		<result property="password"     column="password"     />
+		<result property="status"       column="status"       />
+		<result property="delFlag"      column="del_flag"     />
+		<result property="loginIp"      column="login_ip"     />
+		<result property="loginDate"    column="login_date"   />
+		<result property="createBy"     column="create_by"    />
+		<result property="createTime"   column="create_time"  />
+		<result property="updateBy"     column="update_by"    />
+		<result property="updateTime"   column="update_time"  />
+		<result property="remark"       column="remark"       />
+		<association property="dept"    javaType="SysDept"         resultMap="deptResult" />
+		<collection  property="roles"   javaType="java.util.List"  resultMap="RoleResult" />
+	</resultMap>
+
+	<resultMap id="deptResult" type="SysDept">
+		<id     property="deptId"    column="dept_id"     />
+		<result property="parentId"  column="parent_id"   />
+		<result property="deptName"  column="dept_name"   />
+		<result property="ancestors" column="ancestors"   />
+		<result property="orderNum"  column="order_num"   />
+		<result property="leader"    column="leader"      />
+		<result property="status"    column="dept_status" />
+	</resultMap>
+
+	<resultMap id="RoleResult" type="SysRole">
+		<id     property="roleId"       column="role_id"        />
+		<result property="roleName"     column="role_name"      />
+		<result property="roleKey"      column="role_key"       />
+		<result property="roleSort"     column="role_sort"      />
+		<result property="dataScope"    column="data_scope"     />
+		<result property="status"       column="role_status"    />
+	</resultMap>
+
+	<sql id="selectUserVo">
+		select u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark,
+			   d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.status as dept_status,
+			   r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.status as role_status
+		from sys_user u
+				 left join sys_dept d on u.dept_id = d.dept_id
+				 left join sys_user_role ur on u.user_id = ur.user_id
+				 left join sys_role r on r.role_id = ur.role_id
+	</sql>
+
+	<select id="selectUserList" parameterType="SysUser" resultMap="SysUserResult">
+		select u.user_id, u.dept_id, u.nick_name, u.user_name, u.email, u.avatar, u.phonenumber, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, d.dept_name, d.leader from sys_user u
+		left join sys_dept d on u.dept_id = d.dept_id
+		where u.del_flag = '0'
+		<if test="userId != null and userId != 0">
+			AND u.user_id = #{userId}
+		</if>
+		<if test="userName != null and userName != ''">
+			AND u.user_name like concat('%', #{userName}, '%')
+		</if>
+		<if test="status != null and status != ''">
+			AND u.status = #{status}
+		</if>
+		<if test="phonenumber != null and phonenumber != ''">
+			AND u.phonenumber like concat('%', #{phonenumber}, '%')
+		</if>
+		<if test="params.beginTime != null and params.beginTime != ''"><!-- 寮�濮嬫椂闂存绱� -->
+			<!--			and <![CDATA[ u.create_time >= convert(datetime, #{params.beginTime}, 20)]]>-->
+			and datediff(d, u.create_time, #{params.beginTime}) <![CDATA[<=]]> 0
+		</if>
+		<if test="params.endTime != null and params.endTime != ''"><!-- 缁撴潫鏃堕棿妫�绱� -->
+			<!--			and <![CDATA[ u.create_time <= convert(datetime, #{params.endTime}, 20)]]>-->
+			and datediff(d, u.create_time, #{params.endTime}) <![CDATA[>=]]> 0
+		</if>
+		<if test="deptId != null and deptId != 0">
+			AND (u.dept_id = #{deptId} OR u.dept_id IN ( SELECT t.dept_id FROM sys_dept t WHERE charindex(',' + CONVERT (nvarchar, #{deptId}), ',' + ancestors) > 0 ))
+		</if>
+		<!-- 鏁版嵁鑼冨洿杩囨护 -->
+		${params.dataScope}
+	</select>
+
+	<select id="selectAllocatedList" parameterType="SysUser" resultMap="SysUserResult">
+		select distinct u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.phonenumber, u.status, u.create_time
+		from sys_user u
+		left join sys_dept d on u.dept_id = d.dept_id
+		left join sys_user_role ur on u.user_id = ur.user_id
+		left join sys_role r on r.role_id = ur.role_id
+		where u.del_flag = '0' and r.role_id = #{roleId}
+		<if test="userName != null and userName != ''">
+			AND u.user_name like concat('%', #{userName}, '%')
+		</if>
+		<if test="phonenumber != null and phonenumber != ''">
+			AND u.phonenumber like concat('%', #{phonenumber}, '%')
+		</if>
+		<!-- 鏁版嵁鑼冨洿杩囨护 -->
+		${params.dataScope}
+	</select>
+
+	<select id="selectUnallocatedList" parameterType="SysUser" resultMap="SysUserResult">
+		select distinct u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.phonenumber, u.status, u.create_time
+		from sys_user u
+		left join sys_dept d on u.dept_id = d.dept_id
+		left join sys_user_role ur on u.user_id = ur.user_id
+		left join sys_role r on r.role_id = ur.role_id
+		where u.del_flag = '0' and (r.role_id != #{roleId} or r.role_id IS NULL)
+		and u.user_id not in (select u.user_id from sys_user u inner join sys_user_role ur on u.user_id = ur.user_id and ur.role_id = #{roleId})
+		<if test="userName != null and userName != ''">
+			AND u.user_name like concat('%', #{userName}, '%')
+		</if>
+		<if test="phonenumber != null and phonenumber != ''">
+			AND u.phonenumber like concat('%', #{phonenumber}, '%')
+		</if>
+		<!-- 鏁版嵁鑼冨洿杩囨护 -->
+		${params.dataScope}
+	</select>
+
+	<select id="selectUserByUserName" parameterType="String" resultMap="SysUserResult">
+		<include refid="selectUserVo"/>
+		where u.user_name = #{userName} and u.del_flag = '0'
+	</select>
+
+	<select id="selectUserById" parameterType="Long" resultMap="SysUserResult">
+		<include refid="selectUserVo"/>
+		where u.user_id = #{userId}
+	</select>
+
+	<select id="checkUserNameUnique" parameterType="String" resultMap="SysUserResult">
+		select top(1) user_id, user_name from sys_user where user_name = #{userName} and del_flag = '0'
+	</select>
+
+	<select id="checkPhoneUnique" parameterType="String" resultMap="SysUserResult">
+		select top(1) user_id, phonenumber from sys_user where phonenumber = #{phonenumber} and del_flag = '0'
+	</select>
+
+	<select id="checkEmailUnique" parameterType="String" resultMap="SysUserResult">
+		select top(1) user_id, email from sys_user where email = #{email} and del_flag = '0'
+	</select>
+
+	<insert id="insertUser" parameterType="SysUser" useGeneratedKeys="true" keyProperty="userId">
+		insert into sys_user(
+		<if test="userId != null and userId != 0">user_id,</if>
+		<if test="deptId != null and deptId != 0">dept_id,</if>
+		<if test="userName != null and userName != ''">user_name,</if>
+		<if test="nickName != null and nickName != ''">nick_name,</if>
+		<if test="email != null and email != ''">email,</if>
+		<if test="avatar != null and avatar != ''">avatar,</if>
+		<if test="phonenumber != null and phonenumber != ''">phonenumber,</if>
+		<if test="sex != null and sex != ''">sex,</if>
+		<if test="password != null and password != ''">password,</if>
+		<if test="status != null and status != ''">status,</if>
+		<if test="createBy != null and createBy != ''">create_by,</if>
+		<if test="remark != null and remark != ''">remark,</if>
+		create_time
+		)values(
+		<if test="userId != null and userId != ''">#{userId},</if>
+		<if test="deptId != null and deptId != ''">#{deptId},</if>
+		<if test="userName != null and userName != ''">#{userName},</if>
+		<if test="nickName != null and nickName != ''">#{nickName},</if>
+		<if test="email != null and email != ''">#{email},</if>
+		<if test="avatar != null and avatar != ''">#{avatar},</if>
+		<if test="phonenumber != null and phonenumber != ''">#{phonenumber},</if>
+		<if test="sex != null and sex != ''">#{sex},</if>
+		<if test="password != null and password != ''">#{password},</if>
+		<if test="status != null and status != ''">#{status},</if>
+		<if test="createBy != null and createBy != ''">#{createBy},</if>
+		<if test="remark != null and remark != ''">#{remark},</if>
+		getdate()
+		)
+	</insert>
+
+	<update id="updateUser" parameterType="SysUser">
+		update sys_user
+		<set>
+			<if test="deptId != null and deptId != 0">dept_id = #{deptId},</if>
+			<if test="userName != null and userName != ''">user_name = #{userName},</if>
+			<if test="nickName != null and nickName != ''">nick_name = #{nickName},</if>
+			<if test="email != null ">email = #{email},</if>
+			<if test="phonenumber != null ">phonenumber = #{phonenumber},</if>
+			<if test="sex != null and sex != ''">sex = #{sex},</if>
+			<if test="avatar != null and avatar != ''">avatar = #{avatar},</if>
+			<if test="password != null and password != ''">password = #{password},</if>
+			<if test="status != null and status != ''">status = #{status},</if>
+			<if test="loginIp != null and loginIp != ''">login_ip = #{loginIp},</if>
+			<if test="loginDate != null">login_date = #{loginDate},</if>
+			<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
+			<if test="remark != null">remark = #{remark},</if>
+			update_time = getdate()
+		</set>
+		where user_id = #{userId}
+	</update>
+
+	<update id="updateUserStatus" parameterType="SysUser">
+		update sys_user set status = #{status} where user_id = #{userId}
+	</update>
+
+	<update id="updateUserAvatar" parameterType="SysUser">
+		update sys_user set avatar = #{avatar} where user_name = #{userName}
+	</update>
+
+	<update id="resetUserPwd" parameterType="SysUser">
+		update sys_user set password = #{password} where user_name = #{userName}
+	</update>
+
+	<delete id="deleteUserById" parameterType="Long">
+		update sys_user set del_flag = '2' where user_id = #{userId}
+	</delete>
+
+	<delete id="deleteUserByIds" parameterType="Long">
+		update sys_user set del_flag = '2' where user_id in
+		<foreach collection="array" item="userId" open="(" separator="," close=")">
+			#{userId}
+		</foreach>
+	</delete>
+
+</mapper> 
\ No newline at end of file
diff --git a/jcdm-system/src/main/resources/mapper/system/SysUserPostMapper.xml b/jcdm-system/src/main/resources/mapper/system/SysUserPostMapper.xml
new file mode 100644
index 0000000..2be9ff9
--- /dev/null
+++ b/jcdm-system/src/main/resources/mapper/system/SysUserPostMapper.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.system.mapper.SysUserPostMapper">
+
+	<resultMap type="SysUserPost" id="SysUserPostResult">
+		<result property="userId"     column="user_id"      />
+		<result property="postId"     column="post_id"      />
+	</resultMap>
+
+	<delete id="deleteUserPostByUserId" parameterType="Long">
+		delete from sys_user_post where user_id=#{userId}
+	</delete>
+	
+	<select id="countUserPostById" resultType="Integer">
+	    select count(1) from sys_user_post where post_id=#{postId}  
+	</select>
+	
+	<delete id="deleteUserPost" parameterType="Long">
+ 		delete from sys_user_post where user_id in
+ 		<foreach collection="array" item="userId" open="(" separator="," close=")">
+ 			#{userId}
+        </foreach> 
+ 	</delete>
+	
+	<insert id="batchUserPost">
+		insert into sys_user_post(user_id, post_id) values
+		<foreach item="item" index="index" collection="list" separator=",">
+			(#{item.userId},#{item.postId})
+		</foreach>
+	</insert>
+	
+</mapper> 
\ No newline at end of file
diff --git a/jcdm-system/src/main/resources/mapper/system/SysUserRoleMapper.xml b/jcdm-system/src/main/resources/mapper/system/SysUserRoleMapper.xml
new file mode 100644
index 0000000..492c388
--- /dev/null
+++ b/jcdm-system/src/main/resources/mapper/system/SysUserRoleMapper.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jcdm.system.mapper.SysUserRoleMapper">
+
+	<resultMap type="SysUserRole" id="SysUserRoleResult">
+		<result property="userId"     column="user_id"      />
+		<result property="roleId"     column="role_id"      />
+	</resultMap>
+
+	<delete id="deleteUserRoleByUserId" parameterType="Long">
+		delete from sys_user_role where user_id=#{userId}
+	</delete>
+	
+	<select id="countUserRoleByRoleId" resultType="Integer">
+	    select count(1) from sys_user_role where role_id=#{roleId}  
+	</select>
+	
+	<delete id="deleteUserRole" parameterType="Long">
+ 		delete from sys_user_role where user_id in
+ 		<foreach collection="array" item="userId" open="(" separator="," close=")">
+ 			#{userId}
+        </foreach> 
+ 	</delete>
+	
+	<insert id="batchUserRole">
+		insert into sys_user_role(user_id, role_id) values
+		<foreach item="item" index="index" collection="list" separator=",">
+			(#{item.userId},#{item.roleId})
+		</foreach>
+	</insert>
+	
+	<delete id="deleteUserRoleInfo" parameterType="SysUserRole">
+		delete from sys_user_role where user_id=#{userId} and role_id=#{roleId}
+	</delete>
+	
+	<delete id="deleteUserRoleInfos">
+	    delete from sys_user_role where role_id=#{roleId} and user_id in
+ 	    <foreach collection="userIds" item="userId" open="(" separator="," close=")">
+ 	        #{userId}
+            </foreach> 
+	</delete>
+</mapper> 
\ No newline at end of file
diff --git a/jcdm-ui/.editorconfig b/jcdm-ui/.editorconfig
new file mode 100644
index 0000000..7034f9b
--- /dev/null
+++ b/jcdm-ui/.editorconfig
@@ -0,0 +1,22 @@
+# 鍛婅瘔EditorConfig鎻掍欢锛岃繖鏄牴鏂囦欢锛屼笉鐢ㄧ户缁線涓婃煡鎵�
+root = true
+
+# 鍖归厤鍏ㄩ儴鏂囦欢
+[*]
+# 璁剧疆瀛楃闆�
+charset = utf-8
+# 缂╄繘椋庢牸锛屽彲閫塻pace銆乼ab
+indent_style = space
+# 缂╄繘鐨勭┖鏍兼暟
+indent_size = 2
+# 缁撳熬鎹㈣绗︼紝鍙�塴f銆乧r銆乧rlf
+end_of_line = lf
+# 鍦ㄦ枃浠剁粨灏炬彃鍏ユ柊琛�
+insert_final_newline = true
+# 鍒犻櫎涓�琛屼腑鐨勫墠鍚庣┖鏍�
+trim_trailing_whitespace = true
+
+# 鍖归厤md缁撳熬鐨勬枃浠�
+[*.md]
+insert_final_newline = false
+trim_trailing_whitespace = false
diff --git a/jcdm-ui/.env.development b/jcdm-ui/.env.development
new file mode 100644
index 0000000..d9e93d1
--- /dev/null
+++ b/jcdm-ui/.env.development
@@ -0,0 +1,11 @@
+# 椤甸潰鏍囬
+VUE_APP_TITLE = 姹熷MES绯荤粺
+
+# 寮�鍙戠幆澧冮厤缃�
+ENV = 'development'
+
+# 姹熷MES绯荤粺/寮�鍙戠幆澧�
+VUE_APP_BASE_API = '/dev-api'
+
+# 璺敱鎳掑姞杞�
+VUE_CLI_BABEL_TRANSPILE_MODULES = true
diff --git a/jcdm-ui/.env.production b/jcdm-ui/.env.production
new file mode 100644
index 0000000..93335f4
--- /dev/null
+++ b/jcdm-ui/.env.production
@@ -0,0 +1,8 @@
+# 椤甸潰鏍囬
+VUE_APP_TITLE = 姹熷MES绠$悊绯荤粺
+
+# 鐢熶骇鐜閰嶇疆
+ENV = 'production'
+
+# 姹熷MES绠$悊绯荤粺/鐢熶骇鐜
+VUE_APP_BASE_API = '/prod-api'
diff --git a/jcdm-ui/.env.staging b/jcdm-ui/.env.staging
new file mode 100644
index 0000000..75f471c
--- /dev/null
+++ b/jcdm-ui/.env.staging
@@ -0,0 +1,10 @@
+# 椤甸潰鏍囬
+VUE_APP_TITLE = 姹熷MES绠$悊绯荤粺
+
+NODE_ENV = production
+
+# 娴嬭瘯鐜閰嶇疆
+ENV = 'staging'
+
+# 姹熷MES绠$悊绯荤粺/娴嬭瘯鐜
+VUE_APP_BASE_API = '/stage-api'
diff --git a/jcdm-ui/.eslintignore b/jcdm-ui/.eslintignore
new file mode 100644
index 0000000..89be6f6
--- /dev/null
+++ b/jcdm-ui/.eslintignore
@@ -0,0 +1,10 @@
+# 蹇界暐build鐩綍涓嬬被鍨嬩负js鐨勬枃浠剁殑璇硶妫�鏌�
+build/*.js
+# 蹇界暐src/assets鐩綍涓嬫枃浠剁殑璇硶妫�鏌�
+src/assets
+# 蹇界暐public鐩綍涓嬫枃浠剁殑璇硶妫�鏌�
+public
+# 蹇界暐褰撳墠鐩綍涓嬩负js鐨勬枃浠剁殑璇硶妫�鏌�
+*.js
+# 蹇界暐褰撳墠鐩綍涓嬩负vue鐨勬枃浠剁殑璇硶妫�鏌�
+*.vue
\ No newline at end of file
diff --git a/jcdm-ui/.eslintrc.js b/jcdm-ui/.eslintrc.js
new file mode 100644
index 0000000..82bbdee
--- /dev/null
+++ b/jcdm-ui/.eslintrc.js
@@ -0,0 +1,199 @@
+// ESlint 妫�鏌ラ厤缃�
+module.exports = {
+  root: true,
+  parserOptions: {
+    parser: 'babel-eslint',
+    sourceType: 'module'
+  },
+  env: {
+    browser: true,
+    node: true,
+    es6: true,
+  },
+  extends: ['plugin:vue/recommended', 'eslint:recommended'],
+
+  // add your custom rules here
+  //it is base on https://github.com/vuejs/eslint-config-vue
+  rules: {
+    "vue/max-attributes-per-line": [2, {
+      "singleline": 10,
+      "multiline": {
+        "max": 1,
+        "allowFirstLine": false
+      }
+    }],
+    "vue/singleline-html-element-content-newline": "off",
+    "vue/multiline-html-element-content-newline":"off",
+    "vue/name-property-casing": ["error", "PascalCase"],
+    "vue/no-v-html": "off",
+    'accessor-pairs': 2,
+    'arrow-spacing': [2, {
+      'before': true,
+      'after': true
+    }],
+    'block-spacing': [2, 'always'],
+    'brace-style': [2, '1tbs', {
+      'allowSingleLine': true
+    }],
+    'camelcase': [0, {
+      'properties': 'always'
+    }],
+    'comma-dangle': [2, 'never'],
+    'comma-spacing': [2, {
+      'before': false,
+      'after': true
+    }],
+    'comma-style': [2, 'last'],
+    'constructor-super': 2,
+    'curly': [2, 'multi-line'],
+    'dot-location': [2, 'property'],
+    'eol-last': 2,
+    'eqeqeq': ["error", "always", {"null": "ignore"}],
+    'generator-star-spacing': [2, {
+      'before': true,
+      'after': true
+    }],
+    'handle-callback-err': [2, '^(err|error)$'],
+    'indent': [2, 2, {
+      'SwitchCase': 1
+    }],
+    'jsx-quotes': [2, 'prefer-single'],
+    'key-spacing': [2, {
+      'beforeColon': false,
+      'afterColon': true
+    }],
+    'keyword-spacing': [2, {
+      'before': true,
+      'after': true
+    }],
+    'new-cap': [2, {
+      'newIsCap': true,
+      'capIsNew': false
+    }],
+    'new-parens': 2,
+    'no-array-constructor': 2,
+    'no-caller': 2,
+    'no-console': 'off',
+    'no-class-assign': 2,
+    'no-cond-assign': 2,
+    'no-const-assign': 2,
+    'no-control-regex': 0,
+    'no-delete-var': 2,
+    'no-dupe-args': 2,
+    'no-dupe-class-members': 2,
+    'no-dupe-keys': 2,
+    'no-duplicate-case': 2,
+    'no-empty-character-class': 2,
+    'no-empty-pattern': 2,
+    'no-eval': 2,
+    'no-ex-assign': 2,
+    'no-extend-native': 2,
+    'no-extra-bind': 2,
+    'no-extra-boolean-cast': 2,
+    'no-extra-parens': [2, 'functions'],
+    'no-fallthrough': 2,
+    'no-floating-decimal': 2,
+    'no-func-assign': 2,
+    'no-implied-eval': 2,
+    'no-inner-declarations': [2, 'functions'],
+    'no-invalid-regexp': 2,
+    'no-irregular-whitespace': 2,
+    'no-iterator': 2,
+    'no-label-var': 2,
+    'no-labels': [2, {
+      'allowLoop': false,
+      'allowSwitch': false
+    }],
+    'no-lone-blocks': 2,
+    'no-mixed-spaces-and-tabs': 2,
+    'no-multi-spaces': 2,
+    'no-multi-str': 2,
+    'no-multiple-empty-lines': [2, {
+      'max': 1
+    }],
+    'no-native-reassign': 2,
+    'no-negated-in-lhs': 2,
+    'no-new-object': 2,
+    'no-new-require': 2,
+    'no-new-symbol': 2,
+    'no-new-wrappers': 2,
+    'no-obj-calls': 2,
+    'no-octal': 2,
+    'no-octal-escape': 2,
+    'no-path-concat': 2,
+    'no-proto': 2,
+    'no-redeclare': 2,
+    'no-regex-spaces': 2,
+    'no-return-assign': [2, 'except-parens'],
+    'no-self-assign': 2,
+    'no-self-compare': 2,
+    'no-sequences': 2,
+    'no-shadow-restricted-names': 2,
+    'no-spaced-func': 2,
+    'no-sparse-arrays': 2,
+    'no-this-before-super': 2,
+    'no-throw-literal': 2,
+    'no-trailing-spaces': 2,
+    'no-undef': 2,
+    'no-undef-init': 2,
+    'no-unexpected-multiline': 2,
+    'no-unmodified-loop-condition': 2,
+    'no-unneeded-ternary': [2, {
+      'defaultAssignment': false
+    }],
+    'no-unreachable': 2,
+    'no-unsafe-finally': 2,
+    'no-unused-vars': [2, {
+      'vars': 'all',
+      'args': 'none'
+    }],
+    'no-useless-call': 2,
+    'no-useless-computed-key': 2,
+    'no-useless-constructor': 2,
+    'no-useless-escape': 0,
+    'no-whitespace-before-property': 2,
+    'no-with': 2,
+    'one-var': [2, {
+      'initialized': 'never'
+    }],
+    'operator-linebreak': [2, 'after', {
+      'overrides': {
+        '?': 'before',
+        ':': 'before'
+      }
+    }],
+    'padded-blocks': [2, 'never'],
+    'quotes': [2, 'single', {
+      'avoidEscape': true,
+      'allowTemplateLiterals': true
+    }],
+    'semi': [2, 'never'],
+    'semi-spacing': [2, {
+      'before': false,
+      'after': true
+    }],
+    'space-before-blocks': [2, 'always'],
+    'space-before-function-paren': [2, 'never'],
+    'space-in-parens': [2, 'never'],
+    'space-infix-ops': 2,
+    'space-unary-ops': [2, {
+      'words': true,
+      'nonwords': false
+    }],
+    'spaced-comment': [2, 'always', {
+      'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ',']
+    }],
+    'template-curly-spacing': [2, 'never'],
+    'use-isnan': 2,
+    'valid-typeof': 2,
+    'wrap-iife': [2, 'any'],
+    'yield-star-spacing': [2, 'both'],
+    'yoda': [2, 'never'],
+    'prefer-const': 2,
+    'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
+    'object-curly-spacing': [2, 'always', {
+      objectsInObjects: false
+    }],
+    'array-bracket-spacing': [2, 'never']
+  }
+}
diff --git a/jcdm-ui/.gitignore b/jcdm-ui/.gitignore
new file mode 100644
index 0000000..78a752d
--- /dev/null
+++ b/jcdm-ui/.gitignore
@@ -0,0 +1,23 @@
+.DS_Store
+node_modules/
+dist/
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+**/*.log
+
+tests/**/coverage/
+tests/e2e/reports
+selenium-debug.log
+
+# Editor directories and files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.local
+
+package-lock.json
+yarn.lock
diff --git a/jcdm-ui/README.md b/jcdm-ui/README.md
new file mode 100644
index 0000000..1bac0e8
--- /dev/null
+++ b/jcdm-ui/README.md
@@ -0,0 +1,30 @@
+## 寮�鍙�
+
+```bash
+# 鍏嬮殕椤圭洰
+git clone http://admin@192.168.0.189:8442/r/Jcdm-Mes.git
+
+# 杩涘叆椤圭洰鐩綍
+cd jcdm-ui
+
+# 瀹夎渚濊禆
+npm install
+
+# 寤鸿涓嶈鐩存帴浣跨敤 cnpm 瀹夎渚濊禆锛屼細鏈夊悇绉嶈寮傜殑 bug銆傚彲浠ラ�氳繃濡備笅鎿嶄綔瑙e喅 npm 涓嬭浇閫熷害鎱㈢殑闂
+npm install --registry=https://registry.npmmirror.com
+
+# 鍚姩鏈嶅姟
+npm run dev
+```
+
+娴忚鍣ㄨ闂� http://localhost:80
+
+## 鍙戝竷
+
+```bash
+# 鏋勫缓娴嬭瘯鐜
+npm run build:stage
+
+# 鏋勫缓鐢熶骇鐜
+npm run build:prod
+```
\ No newline at end of file
diff --git a/jcdm-ui/babel.config.js b/jcdm-ui/babel.config.js
new file mode 100644
index 0000000..c8267b2
--- /dev/null
+++ b/jcdm-ui/babel.config.js
@@ -0,0 +1,13 @@
+module.exports = {
+  presets: [
+    // https://github.com/vuejs/vue-cli/tree/master/packages/@vue/babel-preset-app
+    '@vue/cli-plugin-babel/preset'
+  ],
+  'env': {
+    'development': {
+      // babel-plugin-dynamic-import-node plugin only does one thing by converting all import() to require().
+      // This plugin can significantly increase the speed of hot updates, when you have a large number of pages.
+      'plugins': ['dynamic-import-node']
+    }
+  }
+}
\ No newline at end of file
diff --git a/jcdm-ui/bin/build.bat b/jcdm-ui/bin/build.bat
new file mode 100644
index 0000000..dda590d
--- /dev/null
+++ b/jcdm-ui/bin/build.bat
@@ -0,0 +1,12 @@
+@echo off
+echo.
+echo [信息] 打包Web工程,生成dist文件。
+echo.
+
+%~d0
+cd %~dp0
+
+cd ..
+npm run build:prod
+
+pause
\ No newline at end of file
diff --git a/jcdm-ui/bin/package.bat b/jcdm-ui/bin/package.bat
new file mode 100644
index 0000000..0e5bc0f
--- /dev/null
+++ b/jcdm-ui/bin/package.bat
@@ -0,0 +1,12 @@
+@echo off
+echo.
+echo [信息] 安装Web工程,生成node_modules文件。
+echo.
+
+%~d0
+cd %~dp0
+
+cd ..
+npm install --registry=https://registry.npmmirror.com
+
+pause
\ No newline at end of file
diff --git a/jcdm-ui/bin/run-web.bat b/jcdm-ui/bin/run-web.bat
new file mode 100644
index 0000000..d30deae
--- /dev/null
+++ b/jcdm-ui/bin/run-web.bat
@@ -0,0 +1,12 @@
+@echo off
+echo.
+echo [信息] 使用 Vue CLI 命令运行 Web 工程。
+echo.
+
+%~d0
+cd %~dp0
+
+cd ..
+npm run dev
+
+pause
\ No newline at end of file
diff --git a/jcdm-ui/build/index.js b/jcdm-ui/build/index.js
new file mode 100644
index 0000000..0c57de2
--- /dev/null
+++ b/jcdm-ui/build/index.js
@@ -0,0 +1,35 @@
+const { run } = require('runjs')
+const chalk = require('chalk')
+const config = require('../vue.config.js')
+const rawArgv = process.argv.slice(2)
+const args = rawArgv.join(' ')
+
+if (process.env.npm_config_preview || rawArgv.includes('--preview')) {
+  const report = rawArgv.includes('--report')
+
+  run(`vue-cli-service build ${args}`)
+
+  const port = 9526
+  const publicPath = config.publicPath
+
+  var connect = require('connect')
+  var serveStatic = require('serve-static')
+  const app = connect()
+
+  app.use(
+    publicPath,
+    serveStatic('./dist', {
+      index: ['index.html', '/']
+    })
+  )
+
+  app.listen(port, function () {
+    console.log(chalk.green(`> Preview at  http://localhost:${port}${publicPath}`))
+    if (report) {
+      console.log(chalk.green(`> Report at  http://localhost:${port}${publicPath}report.html`))
+    }
+
+  })
+} else {
+  run(`vue-cli-service build ${args}`)
+}
diff --git a/jcdm-ui/dist.rar b/jcdm-ui/dist.rar
new file mode 100644
index 0000000..fd52725
--- /dev/null
+++ b/jcdm-ui/dist.rar
Binary files differ
diff --git a/jcdm-ui/package.json b/jcdm-ui/package.json
new file mode 100644
index 0000000..0c53b8e
--- /dev/null
+++ b/jcdm-ui/package.json
@@ -0,0 +1,90 @@
+{
+  "name": "ruoyi",
+  "version": "3.8.6",
+  "description": "姹熷MES绠$悊绯荤粺",
+  "author": "姹熷",
+  "license": "MIT",
+  "scripts": {
+    "dev": "vue-cli-service serve",
+    "build:prod": "vue-cli-service build",
+    "build:stage": "vue-cli-service build --mode staging",
+    "preview": "node build/index.js --preview",
+    "lint": "eslint --ext .js,.vue src"
+  },
+  "husky": {
+    "hooks": {
+      "pre-commit": "lint-staged"
+    }
+  },
+  "lint-staged": {
+    "src/**/*.{js,vue}": [
+      "eslint --fix",
+      "git add"
+    ]
+  },
+  "keywords": [
+    "vue",
+    "admin",
+    "dashboard",
+    "element-ui",
+    "boilerplate",
+    "admin-template",
+    "management-system"
+  ],
+  "repository": {
+    "type": "git",
+    "url": "http://192.168.0.189:8442/r/Jcdm-Mes.git"
+  },
+  "dependencies": {
+    "@riophae/vue-treeselect": "0.4.0",
+    "axios": "0.24.0",
+    "clipboard": "2.0.8",
+    "core-js": "3.25.3",
+    "echarts": "5.4.0",
+    "element-ui": "2.15.13",
+    "file-saver": "2.0.5",
+    "fuse.js": "6.4.3",
+    "highlight.js": "9.18.5",
+    "js-beautify": "1.13.0",
+    "js-cookie": "3.0.1",
+    "jsencrypt": "3.0.0-rc.1",
+    "nprogress": "0.2.0",
+    "quill": "1.3.7",
+    "screenfull": "5.0.2",
+    "sortablejs": "1.10.2",
+    "vue": "2.6.12",
+    "vue-count-to": "1.0.13",
+    "vue-cropper": "0.5.5",
+    "vue-meta": "2.4.0",
+    "vue-router": "3.4.9",
+    "vuedraggable": "2.24.3",
+    "vuex": "3.6.0"
+  },
+  "devDependencies": {
+    "@vue/cli-plugin-babel": "4.4.6",
+    "@vue/cli-plugin-eslint": "4.4.6",
+    "@vue/cli-service": "4.4.6",
+    "babel-eslint": "10.1.0",
+    "babel-plugin-dynamic-import-node": "2.3.3",
+    "chalk": "4.1.0",
+    "compression-webpack-plugin": "5.0.2",
+    "connect": "3.6.6",
+    "eslint": "7.15.0",
+    "eslint-plugin-vue": "7.2.0",
+    "lint-staged": "10.5.3",
+    "runjs": "4.4.2",
+    "sass": "1.32.13",
+    "sass-loader": "10.1.1",
+    "script-ext-html-webpack-plugin": "2.1.5",
+    "svg-sprite-loader": "5.1.1",
+    "vue-template-compiler": "2.6.12"
+  },
+  "engines": {
+    "node": ">=8.9",
+    "npm": ">= 3.0.0"
+  },
+  "browserslist": [
+    "> 1%",
+    "last 2 versions"
+  ]
+}
diff --git a/jcdm-ui/public/favicon.ico b/jcdm-ui/public/favicon.ico
new file mode 100644
index 0000000..7568a38
--- /dev/null
+++ b/jcdm-ui/public/favicon.ico
Binary files differ
diff --git a/jcdm-ui/public/html/ie.html b/jcdm-ui/public/html/ie.html
new file mode 100644
index 0000000..052ffcd
--- /dev/null
+++ b/jcdm-ui/public/html/ie.html
@@ -0,0 +1,46 @@
+
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+    <meta charset="UTF-8" />
+    <title>璇峰崌绾ф偍鐨勬祻瑙堝櫒</title>
+    <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1" >
+    <meta name="renderer" content="webkit">
+    <base target="_blank" />
+    <style type="text/css">
+        html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video{border:0;font-size:100%;font:inherit;vertical-align:baseline;margin:0;padding:0}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}body{line-height:1}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:before,blockquote:after,q:before,q:after{content:none}table{border-collapse:collapse;border-spacing:0}
+        a{text-decoration:none;color:#0072c6;}a:hover{text-decoration:none;color:#004d8c;}
+        body{width:960px;margin:0 auto;padding:10px;font-size:14px;line-height:24px;color:#454545;font-family:'Microsoft YaHei UI','Microsoft YaHei',DengXian,SimSun,'Segoe UI',Tahoma,Helvetica,sans-serif;overflow-y:scroll}
+        h1{font-size:40px;line-height:80px;font-weight:100;margin-bottom:10px;}
+        h2{font-size:20px;line-height:25px;font-weight:100;margin:10px 0;}
+        em{color:red}
+        p{margin-bottom:10px;}
+        hr{margin:20px 0;border:0;border-top:1px solid #dadada}
+        span{display:block;font-size:12px;line-height:12px;}
+        .clean{clear:both;}
+        .browser{padding:10px 10px;}
+        .browser li{width:auto;padding:0 80px;margin-top:30px;height:34px;line-height:22px;float:left;list-style:none;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAADMCAYAAAAWCXEwAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKTWlDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVN3WJP3Fj7f92UPVkLY8LGXbIEAIiOsCMgQWaIQkgBhhBASQMWFiApWFBURnEhVxILVCkidiOKgKLhnQYqIWotVXDjuH9yntX167+3t+9f7vOec5/zOec8PgBESJpHmomoAOVKFPDrYH49PSMTJvYACFUjgBCAQ5svCZwXFAADwA3l4fnSwP/wBr28AAgBw1S4kEsfh/4O6UCZXACCRAOAiEucLAZBSAMguVMgUAMgYALBTs2QKAJQAAGx5fEIiAKoNAOz0ST4FANipk9wXANiiHKkIAI0BAJkoRyQCQLsAYFWBUiwCwMIAoKxAIi4EwK4BgFm2MkcCgL0FAHaOWJAPQGAAgJlCLMwAIDgCAEMeE80DIEwDoDDSv+CpX3CFuEgBAMDLlc2XS9IzFLiV0Bp38vDg4iHiwmyxQmEXKRBmCeQinJebIxNI5wNMzgwAABr50cH+OD+Q5+bk4eZm52zv9MWi/mvwbyI+IfHf/ryMAgQAEE7P79pf5eXWA3DHAbB1v2upWwDaVgBo3/ldM9sJoFoK0Hr5i3k4/EAenqFQyDwdHAoLC+0lYqG9MOOLPv8z4W/gi372/EAe/tt68ABxmkCZrcCjg/1xYW52rlKO58sEQjFu9+cj/seFf/2OKdHiNLFcLBWK8ViJuFAiTcd5uVKRRCHJleIS6X8y8R+W/QmTdw0ArIZPwE62B7XLbMB+7gECiw5Y0nYAQH7zLYwaC5EAEGc0Mnn3AACTv/mPQCsBAM2XpOMAALzoGFyolBdMxggAAESggSqwQQcMwRSswA6cwR28wBcCYQZEQAwkwDwQQgbkgBwKoRiWQRlUwDrYBLWwAxqgEZrhELTBMTgN5+ASXIHrcBcGYBiewhi8hgkEQcgIE2EhOogRYo7YIs4IF5mOBCJhSDSSgKQg6YgUUSLFyHKkAqlCapFdSCPyLXIUOY1cQPqQ28ggMor8irxHMZSBslED1AJ1QLmoHxqKxqBz0XQ0D12AlqJr0Rq0Hj2AtqKn0UvodXQAfYqOY4DRMQ5mjNlhXIyHRWCJWBomxxZj5Vg1Vo81Yx1YN3YVG8CeYe8IJAKLgBPsCF6EEMJsgpCQR1hMWEOoJewjtBK6CFcJg4Qxwicik6hPtCV6EvnEeGI6sZBYRqwm7iEeIZ4lXicOE1+TSCQOyZLkTgohJZAySQtJa0jbSC2kU6Q+0hBpnEwm65Btyd7kCLKArCCXkbeQD5BPkvvJw+S3FDrFiOJMCaIkUqSUEko1ZT/lBKWfMkKZoKpRzame1AiqiDqfWkltoHZQL1OHqRM0dZolzZsWQ8ukLaPV0JppZ2n3aC/pdLoJ3YMeRZfQl9Jr6Afp5+mD9HcMDYYNg8dIYigZaxl7GacYtxkvmUymBdOXmchUMNcyG5lnmA+Yb1VYKvYqfBWRyhKVOpVWlX6V56pUVXNVP9V5qgtUq1UPq15WfaZGVbNQ46kJ1Bar1akdVbupNq7OUndSj1DPUV+jvl/9gvpjDbKGhUaghkijVGO3xhmNIRbGMmXxWELWclYD6yxrmE1iW7L57Ex2Bfsbdi97TFNDc6pmrGaRZp3mcc0BDsax4PA52ZxKziHODc57LQMtPy2x1mqtZq1+rTfaetq+2mLtcu0W7eva73VwnUCdLJ31Om0693UJuja6UbqFutt1z+o+02PreekJ9cr1Dund0Uf1bfSj9Rfq79bv0R83MDQINpAZbDE4Y/DMkGPoa5hpuNHwhOGoEctoupHEaKPRSaMnuCbuh2fjNXgXPmasbxxirDTeZdxrPGFiaTLbpMSkxeS+Kc2Ua5pmutG003TMzMgs3KzYrMnsjjnVnGueYb7ZvNv8jYWlRZzFSos2i8eW2pZ8ywWWTZb3rJhWPlZ5VvVW16xJ1lzrLOtt1ldsUBtXmwybOpvLtqitm63Edptt3xTiFI8p0in1U27aMez87ArsmuwG7Tn2YfYl9m32zx3MHBId1jt0O3xydHXMdmxwvOuk4TTDqcSpw+lXZxtnoXOd8zUXpkuQyxKXdpcXU22niqdun3rLleUa7rrStdP1o5u7m9yt2W3U3cw9xX2r+00umxvJXcM970H08PdY4nHM452nm6fC85DnL152Xlle+70eT7OcJp7WMG3I28Rb4L3Le2A6Pj1l+s7pAz7GPgKfep+Hvqa+It89viN+1n6Zfgf8nvs7+sv9j/i/4XnyFvFOBWABwQHlAb2BGoGzA2sDHwSZBKUHNQWNBbsGLww+FUIMCQ1ZH3KTb8AX8hv5YzPcZyya0RXKCJ0VWhv6MMwmTB7WEY6GzwjfEH5vpvlM6cy2CIjgR2yIuB9pGZkX+X0UKSoyqi7qUbRTdHF09yzWrORZ+2e9jvGPqYy5O9tqtnJ2Z6xqbFJsY+ybuIC4qriBeIf4RfGXEnQTJAntieTE2MQ9ieNzAudsmjOc5JpUlnRjruXcorkX5unOy553PFk1WZB8OIWYEpeyP+WDIEJQLxhP5aduTR0T8oSbhU9FvqKNolGxt7hKPJLmnVaV9jjdO31D+miGT0Z1xjMJT1IreZEZkrkj801WRNberM/ZcdktOZSclJyjUg1plrQr1zC3KLdPZisrkw3keeZtyhuTh8r35CP5c/PbFWyFTNGjtFKuUA4WTC+oK3hbGFt4uEi9SFrUM99m/ur5IwuCFny9kLBQuLCz2Lh4WfHgIr9FuxYji1MXdy4xXVK6ZHhp8NJ9y2jLspb9UOJYUlXyannc8o5Sg9KlpUMrglc0lamUycturvRauWMVYZVkVe9ql9VbVn8qF5VfrHCsqK74sEa45uJXTl/VfPV5bdra3kq3yu3rSOuk626s91m/r0q9akHV0IbwDa0b8Y3lG19tSt50oXpq9Y7NtM3KzQM1YTXtW8y2rNvyoTaj9nqdf13LVv2tq7e+2Sba1r/dd3vzDoMdFTve75TsvLUreFdrvUV99W7S7oLdjxpiG7q/5n7duEd3T8Wej3ulewf2Re/ranRvbNyvv7+yCW1SNo0eSDpw5ZuAb9qb7Zp3tXBaKg7CQeXBJ9+mfHvjUOihzsPcw83fmX+39QjrSHkr0jq/dawto22gPaG97+iMo50dXh1Hvrf/fu8x42N1xzWPV56gnSg98fnkgpPjp2Snnp1OPz3Umdx590z8mWtdUV29Z0PPnj8XdO5Mt1/3yfPe549d8Lxw9CL3Ytslt0utPa49R35w/eFIr1tv62X3y+1XPK509E3rO9Hv03/6asDVc9f41y5dn3m978bsG7duJt0cuCW69fh29u0XdwruTNxdeo94r/y+2v3qB/oP6n+0/rFlwG3g+GDAYM/DWQ/vDgmHnv6U/9OH4dJHzEfVI0YjjY+dHx8bDRq98mTOk+GnsqcTz8p+Vv9563Or59/94vtLz1j82PAL+YvPv655qfNy76uprzrHI8cfvM55PfGm/K3O233vuO+638e9H5ko/ED+UPPR+mPHp9BP9z7nfP78L/eE8/sl0p8zAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAC7ESURBVHja5Lx5dFRV1rBfgHwYRQQVtB26ZWhtabtfeUGxGxFbUGZF8RMHGkVbRkekVYiKisicVhE0gEwBokgDAhEMMSSQkAECwcxkrlRSqVTqJqnxzs/vj5t7qUyAvr9e37fWV2vtleSm6p6n9t5nn733OVU2RaUaEP5PiqJSbeMXPBTA5/Xhzk9Vnd9vo3HFx21E2LYJX9IRgh6npvyCe9uaqS4K4C3IpXHFx9S99CTuJ8Z0KLVjRlA7ZgTuJ8ZgXxmJL+kIlwAkXBQk6HFq9pWRVA8fSvXwodYgdS892a6EA1UNvouqwXdR99KTeAtyfz2IL+kI1cOHYh9wqwVwKWJqpXbMCOv19gG3Imzb1JF2OgZxfr/NukH4jcNVfyEAE8IU+4BbKet1PfaVke3BtA/i/H6b8aIBt7a4mWmaC0nr55vmqRp8F5V33Mm5LhHtwbQF8SUdsSDCb1I1+K42g1xIWgOYYh9wK+e6RCBs29QxSIWus37aJM51iWjx4so77mwD1d5AHQ1eecedlN9yuyVlva6nrNf14Q7cEmRn4W7u3T2E9ME3UX7L7W1uZg5Weced1s3sA2613ql5LXzQjuRclwjcT4wxTXQeRHC7GLdnHPeensiCVwa3e0PznZk3EbZtwluQa0kofz8NcVNxr++Ce30XnNuv61Bcu7viXt8Fvyu7JYipjfGHxzD+8Bh2j+7fAiZcC+Y0zPDIbCyD6DyV6DyVeDcIQR2C39J4oieNJ3oSOnkVcnZ35Ozu6MVdDHF0N6S4C43OqJYg/0ydzb27hzDx0FjuPT2R+asfa6OVsl7X40s6QoWus/CQk6fWZPHChhxe3lbMCxtyrN9TyxSQSwidvMoC0XK6tRGybPjSRmOuNUKVo4Zxe8YxIu4+Jh4ay/jDY7j39MQWWjnXJYLGFR9Toes8tSaLiavTrIHDxfxfapkCwW8hy9YuhCmhk1fR1FRnaCS1NM4yy8RDYy2tjIkZRXq/HtYsCnqc2sJDTkYsTrU00J6YkEJQR7M/eEGY0MmrcOenqjZA2JmyzTJLuJiOe65LBHUvPUmGR2bE4lQmrk7jqTVZHcrE1WkMWpRIdJ4KnpUXBCHLRl3e16EWIOEaMU00/vAY9na/gsYVH/NdgYe+8w9bMBeSQYsSWXjICcFvL2ga+dhlFwcJ10rjio/ZklprgbSWiavTWvzdd/5hXt5W/OtATC201sq9u4eQ+PVijmSW0nf+YQYtSmTQosR2gUYsTmXQokT6zj9saeRCpmkJ0hxD2gOZeGgsI+Lu45+ps7FXlFmDmDDtSd/5h+k7/zCpZQpa9cwOQciyIR+77LyzFhXlMyZmFOP2jLP8orVWRsTdR2ppHFtSa+k6ZZM1WHvSdcomwyxySceayO4OWTY88TdirygzUkWf18eL2//RQiutYcwYE/Q4tagDOUQ8uo6uUzbRZ3qMJV2nbCLi0XU8tSbrolNXzu6OfOyylgEN4NOkaO5acw/j9ozr0ET37h5imehIZimPL91rAfSZHsOQBfuISS7E7vaTETeX0MmrOoQInbwK+dhlNKWsahni0zPSuGvNPW1M1BrI1NrOwt0WkCn2ijJSS+MYt2ccuQk3oxd36RCi8URPY+HLT1VbgGiSzPsx71laCddMe2Yygf6ZOtuScXvG0XfJn/n8YL+LQnjibyQ34WZ8Xl/bfKSoKL+FVi4EYwKZcu/uIQzaPoExMaPQcrq1ADFX33AI1+6u1OV9HVI6ShU/TYqm75I/dwjTHtDEQ2MZt2ccg7ZPaGGScIDWEBlxc42UoSMQ00StYdoDCgcbtH0Cbx+8p40ZTIBwiFM7RmB3+y+exZvT2YRpDdR6ZoVrw1xRWwN44m/Euf06A6Ki7NLrmnDNmH7TEdSg7RP4/GA/yLK1GdwEKNzSk1M7RlDlqPl1JefOlG2MXTGmXaAxMaMsB/XE34h4tH+7ANlrB7T2iV8OAlDlqOH9mPcsIBPKlF3R16Ad7GwlxoVberYAKCrKv1ghfmkg5sPldLIzZVsLqLErxpC9doAlp3aMICNurlGyVpRdSAu/HqS1Q58rd1JUlI87P1UtKsrHXlGG3e1HCOoov+x2wiX3RxT+o49L1IgutXxVUCfDIxNfLraQDI+M3e3/NdCXbhohqBNfLrIsVzZqmoT6dmXG0SBLTrmJLxd/CVRLECXcDGFaSC1TmHE0yKg4B0P2uxiy38WoOAePHaptAfHYoVqG7HcxcGc5o+IcfFfgsbQUPoYoSa213BbE78oGucTSwpJTbobFFjNgbQHdvi6g8/Z6Om+vZ8h+VxsQE7T/97UMWFvA+Og0UvIryfDIZBQ4CeXvt8a5IAhAY/RImlJWUaHrPHaolhuXFXHN+8e58qNcbomq5P6t3xG973WePLzPgnnsUG0LiP7f1zJwZzk3LisyctfSOFxOJ4lfLzYToQubxu/KpmpWBFWzInguOokrP8ql7/zDRMxLpFfUabasHwlZNnITbmbgznI6b6+3Bu7/fa2lrW5fF9Ar6jQD1hYwLLaYx5fupdi+EiGok748koa4qa010xKkKWUV2UM7kd6vB7tH9yfpnUFkLzQiZOGWnmgHO9N4oie9ok5bA4YPbkqvqNNc8/5xIuYl8tSaLOLLRXambENXF+PxNJD0ziAanVHhYaEliH1lJD/1iqD0qSsIzu2M/N550TZ3QjvYmS3rR1qDtwdhgpgwnabGMj46zRjQsxJdXYw7P1X1pY0GuaRjkMKxPah5qxuV8y6nct7l1LzVDfdyo6miHexM+ou9mblwKfdv/Y77t37HNe8fbwMQDhIxL5FOU2PZklqLJjUYdU7wWxBuN+ricBAF0KQG6pcNovZpw0fCQao/MEBcu7tSOLYHjnu7EZzbmeDczqyfNokrP8ptMXi4XDnzAJ0n72TIgn1oUoMB4VlpgIjj24I0payi9KkrqHj+Ssth2wM5c38f8p68D2nbHKRtc3h86d42A/eZHsOVMw9Y0nXKJmxDvyS1NA70z8Gz0qh5hNvbzpr6ZYMofzyiBUwLkOVdjfR/eVcao0dSl/d1aHx0GhHzEi0TXDnzAJ2mxtJpaixdp2yypM/0GLrcs5D3Y94ztNDsK7qjuxmzDBBz2rYGqZoVQc1b3dr4yfppk+g8eWeLd91aAxGPrqPbyKV0G7mUiEfXMWdz+nmQ0Jsgn1AbT/SkMXrkeZC6vK9DpU9d0S5I5bzLqf6gq6UV7WBn5q9+zDJBuEQ8us4SE6LLPQvpcs9CjmSW4ndlo1XPNBxWLiE34WbSX+wNapEBEsrfT/njERSO7WGBmDA1b3Wj9KkrSO/Xg1WjBjJl/CT+8sQ8a0BT/eGDhwN0uWchXe94ia07YkE+oSLc3gxyQt2yfiSrRg0E+YRqgRSO7UHh2B4UT7ragqmcdznFk67mp14ROO7txpTxk7AN/bLFgN1GLsU29EvrejiACdG59xQjKgu3GzVP9UwIvcmCVwYb102NmBHVBDFNVDUrgjP39yF98E0E5xox5Dcj5lsDhwOYQObg4dK59xR2RV8D4njEo/0NIEd3dkVfgy9t9HkfMTWSO6pXG63kjupF8aSrqXj+SoJzO1M573KmjJ/Eb0bM5y9PzGPBK4Mp3GKUEFvWj+Q3I+a3AOjcewp/eWKesUQ0T1mz2att7oSU9+F5EE2SqXvpSbKHdrIGNmHCoapmRVgh33LezZ3QNncyloGDnVnwyuA2IFvWj0Q+dplREzu6Wy0r9/KubVvg9pWRpPfrwZn7+1haMSHCxdSM/J4RWWufjiC9Xw/m9PgtN9w0uo1JbrhpNI0njAXTrAIbT/TEvb4LjdEj2641vqQjpPfrQfrgm1qYKHxKlz51BbmjerFj4G2WtAYwtWDKglcGG2ZoXrldu43AWDUrAmnbnLaRVZMayHvyPn7qZThoa38pfeoKap+OIDi3M6tGDeSGm0a3GTT82g03jeaGm0bj3H4d8rHLrN0I93LDpDsG3kb68si2a425hfZTrwjSB9/UBiZcM+YM6ghoyvhJpL/Ym+yFhknc67tYQVF+z3gjc3r8Fuf32zpOFTMeHXpRGDNfMYF2j+7PqlEDWTVqIOkv9rZ8SNvcCff6LlTOu9yK1Okv9mZOj9+S8ehQNKmBDhs17vxU9adeES1gwoHKH49oFyhcwhfKynmXWzOu4vkryR7aieyhnQjl7+84QzNNJGzbxN7uV1gw7WmntYZaLw2mmNdrn44ge2gnztzfx9od7zBnDa9t0pdHtgsTDhRustaaCndwEyLj0aG481PVS9r3FSUJj6eBrConMZHvnodpntrh2gkHCgcLl/TBN7G3+xXGLMlIo0LXjU7ixeoaUZIQ3C7OlTtJya8kJvJddgy8DctvWgGFaylcHPd2Y2/3K5jT47esGjWQrTtiyapy4nI6jUrvUmpfUytFRfmkZ6SxdUcs66dNYsfA2ywNtQBrJeb/dgy8jZjId/kx4YgF4fP6Ln1L3uyhhWvnSGYpOw6lEBP5LuunTWLDAw+x4YGHrAi74YGHWD9tEuunTSIm8l227ohtAyBK0i8/pNDagTVJxuf1YXf7OVfuJKvKMF16RhrpGWkcySwlJb+SrCqn1awRgjqaJP9nO0b/Zxo1v+ahS0ZqKJ9QCX5rJMyhN42aRj6h/udB5BKjiAp+i64uNrJ2M0Vs3rUiy4aU92G42X49iCYZDZjUMoX4ctFIcILfGgVU6E0LwEyCxKP98aWNxpc2GvFof+RjlyHlfdjxWnOxh93tJya5kIWHnDx2qJbnopP4NCmaYvtKC0LL6WYkQps70RA3laaUVbjzU1V7RRn2ijK8BbkWUJsM7VIAog7k8MyuPKtD1AJA/9zQQpYN9/oubFk/kpkLl7J4a0KbtrdZa/vSRrfMWS8GcSSzlGd25TH5VIjptTpR9T5SS+OMsrHZD3RHd7SDnTm1YwSzY2KsTtL46DSei07iSGZpm/tKeR8a5gnf0+vI8zfE5zAstpjptTrvifBJeeZ5LTQDkGXDtbsr0fte59mjDmaWaUyv1ZlZpvH3XJlRcQ6Grj5OTHJhy/t7VhrpwMVAog7kMCrOwcs+nZWaccak2L7S0oLpC6d2jGDJiUyWN8E6FVZqsLwJ5ruwYO5O9jFoUSIb4nPOT+/gtxf3kZjkQobFFreAaHRGGZoQbm+hhWd25fHsUQevHilgbo7bAmoNM2S/i6Grj3Mks9Tolcgn1Hb39MzHuXInw9edZrJd4z3xPISuLrYgCrf0ZOuOWKLzVFLLFDIKmlfr5EJmHMxhfoWvDczkUyELxl5RduFUUZNkIvdm8+BpkZd9eocQPyYc6XDnocpRQ+TebObmuFmptdTK5FMhBqwt4K1vMi4cWTMKnIyKczDZrvFJeWaHEBdrbVc5aphxMIflTR1rJaPA2TFI1IEc7k72tZwdYRCLtyZc6h4MMcmF7WrlwRSRAWsLiNyb3T6Iz+vjmV15jIpztIHwxN/I7JgY4svFS47CHk9DG62Y5hm4s5zx0Wntb0CnlikMiy3m06ToFpFSO9iZnSnbeGZXHkcyS8kocF6SHMksZc7m9AuaJyW/si3IltRaZsfEGNM09KZVs2bEzWV5EyzLlXn1SEG7MuNgTruy5JS73dlzd7IvPMi1BIlJLmRnyjbLJFawar7ZHi5NdrSS9jRyd7KPXlGnzQDXyjSlcYY2mk1SuKUnS05kslI7f9M9/HKgdaoh74nn/cR02NV7M9t2A9A/t/qf2uZOvB/zHvNdxk3Mm0bV+36VzK8wxHTWVutPmEbkE6q1hjQ3/yefCvGeeB7k1SPGlLsUeeubDOtnezJnczpvfZPBuXJnGEjzAqSri9FyulG4pSf3b/3OCvErNQNmxsEczpU70ST5kuWXJc9yiZXemQ3du5N9TK/VedmnW1qZm+M+v3r+gpTS42nA42nA5XRa4vE0hFd8zSDBb63cInvtAAYtSuTuZB+T7ZoFYy7tz+zK6+igQZtHRoGTyL3ZLab4M7vyGB+dxpAF+1i8NaEliLmWyNndsa+MZPi60/T/vpaJhTKT7ZqllZWaoZW3vsnA42m4IMS5cifPRScxN8fNeyK87NOZXqszsdDITa55/3i4dgVb0OPUTG2IR/vjzk9Vt6Qau5R3J/uYWCi3MJEJM2dzOkcyS80Q3WKrPia50IIIX2cmnwrxYIpIr6jTPBed1Mo0apFgpv0NcVMR3C5ESWLO5nS6fV3Ag6fFdmHmV/iYcTCHyL3ZRB3IsSRybzbP7MpjfoWvXYj+39cyZME+c7aEgTQ36smy0RA31dostrv9DF193IIJ9xcTxgSam+O2xAQwg9fMMo2JhTIPnjYgBi1KbC+RPq8REyR8iT9X7rRgWptpvssYLBwqHGB6rc7fc2ULYsh+F4MWJbLjUErH09c8ytcaxNTMCxtyGLC2oIUDT6/VO5TJdkMLJsTAneUMWpTYNotvE0eaj3rKxy6zun2t69mdKdt4fOley4lN35ls11pIOIC51D8XnWQu9xcGUQCteibyscuM5n31TKNqD5fm1H9DfA7PRScxdPVxhsUWMyy22Dq4MGS/i2GxxQxfd9oC2HEopb1WVcdtCU2Sqcv7OmTWpGbRLOV9SCh/P0GPUwvPvDIKnMQkFxK5N5s5m9N5LjqJ56KTeOubDFbvzSQlv7LN1P5FxzZ8Xp918v8SWk5WsWStLbr0a5oLHRdY/+GjPP8vtq7+0yCiJOHz+hDcLlxOJ2bzxeV0Irhdlk/9x0B8Xh9VjhoEt6s5rZTaFU1qQHC7qHLU/PpZ05EGqhw1uJxO0CVESSIlv5KoAznM2ZxufTJgzuZ0og7kkJJfaR1mcjmdVDlqflkc6ahSs1eUWdMzJrmQQYsSrYMJNy4raiHmYQWzD2IC2SvKLpa/dAzi8/qsc6cZBU6GLNjHlTMPcEtUJVMSdd45qRGdp7KxDOvDPu+c1JhxNMgtUZVcOfMAQxbss0K7vaLsQqbq+GCtCbEhPodOU2O58qNcZhwNsrMK4t0Xlp1VMONokCs/yqXT1FgrE7sATPvbJK0hblxWxDsnNWugvc7zcqFry3JlbomqbANzSdskpk9kFDjpOmWTpQnzne6sMgbbWWWYY8kpN0tOuYnOU1v8z9TcOyc1blxWRNcpmwwz6dLFjxr7vD5rY+eO13YSMS+Rh/co1iAby4wBluXKLDnl5rsCD1lVxk7FdwUelpxysyxXbvHcjWUwYb9CxLxE7nhtp7X10spELUHMMiHqQA6dJ+9k8KYaJh1u6ZRLTrnZklrb+hS3lURtSa1lySm39fyNZTAlUWfwpho6T95p1rqtS5LzICapJsmWNkbEBpiSqLMs1/gY3DsntfAuT4tDlkrYtci92bxzUmNjmaG9KYk6I2IDbbTStsBqjhma1EBKfiVdp2xiwNoCHt6jMOmwxjsnNev46KWUkaIksfCQk2W5Mu+c1Jh0WGPCfoUBawvoOmWT1d4Miy3nQczIuXpvJp2mxjJ4Uw0T9hsg09KM6fhcdBIxyYWXJM9FJzHjaJBpaTDpsAEzeFMNnabGGhVec+RtA1LlqAFd4vGley0Q8wZTEnWmpWGdWX3sUC3PHnW0K+b/n0qoZ1oaTEszfCQc5PGle0GXwv0k7PxI87S9EMjMMo35rvMdILPDbErrzlA4iOmw4SBh0/iXgUxLg8mnQvw9V2Zmmdau/D1XtpoxpiYe3qPw8B6FW6IqreOCvwpkWhqMinMwaFEi46PTfrFMXG38HLr6OHe8ttPykXZNYzrr4q0JdJoay4C1BS2cdfCmGuZsTrd6Hv/T5ozZJ7no9L1xWZE1fU0bD193unXx3GESFZNcyIb4nDazaUN8Dh6PkTy1O307CmgT9itM2K9YWnkuOumi26wTV6dZR43NXOXKj3LpPHknEY+us0DaDWiWnwCr92bSdcomBm+q4eE9ShsThTXh2jRn5mxOZ/CmmjYzZkRsgE5TY40Q33bhu/iiF66VcJjh604TuTfbUnnk3myGrzttQZgzZtJhzQrvfabHWGNccNELnz2tfSUcJjxADVhbwIC1BdYsMyOp+fyH9yhWGnAks/TS0gDTV4qK8q2NxU5TY7klqrIFTDhQ6+gZ/hwzdoSbpKgo/9LPj5hnR8yUwEwVw810MRkRG7BSRXPpLyrKv/RUsT2YI5mlLZLnEbEBK1q2lhGxASt5vuO1nZY5ioryL5TJX7icENwuioryjV1rr4+oAzkMWbDvouXEkAX7iDqQg8/rQ5MaLgZxaQWWJslWSWkWWBkFzl9UYP2PvgjFPNrj8/osM/2YcIQfE46QnpFmfL7K7SLocWpBj1Mz6+D0jLQWzzPb3b/6aI8SVnCbvXTTVOZxno6kqCjfKlPNUH4pIP9XPGz/N319UFnrf2iKLGi6LmggqCBoIOi6JuiqIqCrgqIrgqyrgoYu6JpiiK4LKgigCpquCCEdQdVVAU0VdP2iMGW29tplmtbcQNQ1QEXXNDQdQGsWHZBbvdQsKkTQfaiaBJrc/PyLPpQ2zqqbL9U10GV0TUbTZUCyQAoaJPaVinx5RmbVKZnVWRpf56r8WKlQFww2Q4bf8VdMXwsEtfkdGb97xSAb8yRG7df4zYYQ3deEsK2WsK1UsK1U6LIqxJWfKQzcEODVw0GS7KbG1F8Pout6C7WuL5Dpv1PBtlLEFgWXfyHTY61Ery91rvkiwLWfB7h6jcxV/5LoskLF9gl0+tjLI7FesuuxzKnrHeqneQdL143Bjacj6wqg4ZFUph8JYvusCdsXIldvhGvXi/T+SuS6dQrXrZO4fp3Ib76UuH5NiD6fi1z/mcgNnwa5epWMbbHG1StEvsoSjbeoq2i60h6MYNN1XTAhNF1vdlBoVFSG7/Nh+1Ti2o1Brl8v03uDyDVfN3DDVz5u+FKh15cKvdbp9FoHvT5X6PW5wjVr4LrPda6NkugTJdL1EwXbIpkVx5sdGaXZ8S9gGgNIJ6ipPHgghO3TED23h+ixTafXZpmb1ofos0ml+9dw1VcaV3wapMvKIF1WSVz+qULPzxV6faZw9Wc613yq0Xt1iN9Ehei+WMG2QObz03JHDtxsGk07P2XRmZ/hx7ZG5rqtMjdubqTHFonrNov8doPMZRvA9pmPqz8X+MNWhb/tkrg/VuGWaJXLPmmk85Imen6m0+sz6BMlcsNqP9etVujysU63jwIcrwy1N6UFm6Zrgma4KKBxrE7lyq999PnaT58dcMNWjV5bFa7d6sP2lcj/+szP6/FNHK2SqQtpSKqIKItUN2psyJH52yYXtkV+uq9UuP5fMj1XqVy9WuWGFSE6LQgxbHMQv6kVXW92B12wKZouSEjGNNMVJvwgYdugcGOsym+2q/TZqnD9dh3bVz5u3h4guVJtnpJa808zkJlBMMS7SQG6vB/gimUKvVdK9Fmu0nu5zLXLZGzvaWzLDhggmoysqwYIKoKqG+rKqVO5douP62JUfvutxg2xCn1iZTpv0rgpRuF0XQAIgRJElSUURUWWZWRZRpFlgrIKeIEg7yaC7X2FXkslei+XDVkmY1sQ4pFNDaA3hwcdNF0XbGjNZwNQWXZaxrZV5XexMjftFLnpW4ne34rYNvjZUywBQUJqEEkMoEk6oqIgySqipCCKEt6Qis8fRNEaAB+TtijYInV6Lwtx7VKRPstkIj5S6PGBRGFtwFCgApquCDYFTQANXZeZkiARsVPnlu9kfhcr0/cbiYivA4w94DM0oet4VQVJUQiJGiFRIiTKBEMSAX+QhoBIvU/C1SQCfpIKGrl8kZerFitcu0Tkuk9ErlsiYXtDYuMpYyobE0gVbIouC6DiDsgMiwtx406Z/rs0+u6WGPCNSI8tIZbnSoCCEvITkBRkWSMUkAgEJbz+EE2+IA3eAPUNjTR6fNTWSni9PuoFN/d8KtBpkcg1n3jp82GQ3h/6sc33seAHb/P6pYOmCTY0VQCNEkHhrgMhfrdL5k/fafT/XqT/boU+sRI/2r0AhESFYFDCF1TwBSWa/CE8TQHcjQFcDX6cdQGq63w43PWU1AoEmup4emMjtvl+enzop/d7Aa57N4Btvo/Z37jCHBzBpuqaAHDOHWDo/iD99in8+XuZO/er/H6fxsB/h0irDgGqoYGAhOAL0eALUd/oo87TRK2nCUddI3anQKXTTUl1DUVVNXga6nh2mwvb6066L3Bz3btOekU2YXtd5MVNDmuVVtEFm6brAmiUu4OMPODnjv0idx+UGHpQ4q6DEnf928+h0iCg0egN0OgXqW8MUCd4cXm81LgbqHIJlDs9lFd5KK90U1hWQ3GlgLOqlrs/rsQ2q45rFjq57q0yukc6sL3iYc62akBDR0fRNcGmq5oAQYSAyuQEibsPhnjgkMYD8T4ePOTnv/ZrfJrtBTWE4A3ibvRTJ3hx1jdRXddApbOeMoebEruL3Ao3p8vqOVVSR1JuDZkFtbywvgDb0zl0eqmanm+Wct2bFdhmlvP2Po/hH6qIrmiCTdNUAVVElTVeyfTz10My435UGHNE5JGfJIYf1ZiV4kFo8uILBKirD+LwBHC43Dhq6ymurqfAUU9ORS05RSU0NHmQVRW/JCMqOho6354U6DEri04z8+nxWim2fxSx8ZgLEAlJCqoiCzZZUwVZVECDjUVNDD8s8sRRlSmJOs8mwbPHZJ466iO2yI8aDNJU56a8tpGqaicOZx2FVfWcLa8lq7CMBn8IHfAGZQKSik/SQAoBOjEZtdiezqTTS/l0fzmPrFIBNB9CUCcoSYJN0TTBKymgS5TXBXn8pwCTj8lMT1WZmarx+nGR2Rk680+GOFleh9/bgMtZR3V1HYWVLvJKajiTV0pVjRsV8IVEgrLaLApeERSCAAx5/xS2+48zZvlZAmKIQFMTHq+PppAi2DRdFQIyyKIfRImoMz6ePO7lpUyJl08r/PN0iMjTEh9kS6zNEUgp92GvaaDAXstZh4DLG0JoChAMyviDMn5Jxi/K+EISIVnFr0h4JWPZ33a8mNteSCI6vhpZbMDhaqChyYfHHxRsmhYURBECoRDoMvkukVfTFN7IlHk7W+aDXIlVOSHW5ob4qhi2F4v8WNLIiSov5wLgkVVERSUYMqa2LyTjF1UCkkpQ1vGLImJAxCsai2SdKFJQ6aG0ooqK+gBuVxOCTxBsuq4IkqQSFCVCkgyqzg8lXt5J9/H+WViVJ7G+KMSOEoVdJSp77DJxdRrH3Rq5goLDJyMERRqCIt6QbPiHqBAQFSRJJSCrhGSZJklDUs/nIefsNRRXe3DWefE0NjUf21BURFEiGDRWVH9I5Nu8Rt7Pk/lXocbWIpFvKzT2VSr8YJdIcEqk1Svke2TsPhV3SMYTEmkISngDCr6QTFBSCUkqQUnFL2kEJUNLflFF1aGuyUepow6HuxG34DdyVkVRkCQFUVLxBWR0ScEfFPmuuIG1hTIxpSr/rpA46FBIqJHJdGmcqVPJa1Co9MrUBiTcQQlPQKYhoNAUUvCJCn5JJSApBCTZEr8oEVJU/IpKiaOOmnov9Q1+QyOqqiErGqKiIYk6/mAATQ4QalRItPvZU+EnvkrmxxqJRJdIVp1KTr1GQaNChVei2idTE9BwBRTqAzKeoEyjKNMkKvglhaCkNAMZogAeX4DS6npcDQE8jYHmM0aajqLqyLJOSNbwSTJev0woEKCxyU9OdZCEkgAJ1UGSBYWsBo3cRihq0qj0KVT5ZBwBjdqQRn1IRhBVGiWVRlklqOiIikZQ1hAV4ytjJE2n0ummqt6LU/AjNAYEm64jaBqoqo6iaEiKhiirBESVhkAQr9eH0ChSUu3nVGkdGY4mUmt8ZLoC5DWoFDUplHpVKnw6VT6ZWn+IuqCEJ6TQEFINzUgSflXFJ8nUe304XALVdQ3UNwaob/TT5A0ZILoO4TCyrBKSZHxBGcEfxNPgpdETwO32U+ZoIKesnrPlHrLtbn6urCfPXk+B3U2R3cO5qgbOVTVQUilwrkKgtEqguLKe4sp6yhwNlNg9VLkEhKYgjd4QTX6RYFA+X2Dpuo6maaiqiqqqKIqGKKn4QwrekERjIIC70YenMUBjk0S9EKK23our3ovb48Xj8SI0BfD4ROq9IdyNQeoa/Lg8AZxuPzV1PuobRASfguAN0egP4Q1KBEMykqwKNkAxMnpDNM1oSxhQGrKiI6oqTapIkyTiDYUIiDLBkEwoICOGjHghKxqKqqCoEooqEVJFgkqIkBIiKIsEpBB+MYA/FMAXkgiICiHRmK2KoilWo6bZRIKu61bjRdd1QdEQVBVBkzRBlVRBFhVBVTRBUXRBknVB1hAUECQQNF0XUHVB13RB0XRBVDRBUjRBUTVBUlRBlBRBlGQhJGuCJOuCouiCpuqCqqpl/7Eemqor5HnS2Ja/hPezpvCP1PuYlfo3vvo5EnfA0baH9qs+CKZpBIIh7DUuyuw1lNprqHDU4mnwoqoamq5xyn2YVTkv8cKJO3n+TH+eTB7Ao/H9eSr+TnbmrfyfgdiddZzKKaK0yklhuYN6oWVfvabay+6Tu3gzaSJPpPZm9E9XMmnvH1n60wKSanZypuEg35WuZlrCMLb9vPSXgzicdWTkFLX7vya5Dq/spk62s8v1AW+cu53ns29kSd6z/Fi9mZ/L8tpqVFfZeHYxBe7MSwdJy85v8Xd1oJwDFRtZlTeTD88+wcKsMSzMGsv8rL8wNbMnc7LuJN6xg6AcsF6TW1xBkzfQct9P8pDrSkfT1QuDKKrKz8UV1t+V3kKi89/m1YyhvHlyMPOz/ouFZ4fwYe59fJAzjLfO3s66wuep8p7jbF0iUTkzOe76/rzZ6jxUVteGtch06gL2C4PIikJFtcv6e3/ZeuamDOHNU//NivwxfFY8jnXlE/iyYiKflz/Eh4WD2Gv/CL/YQIJjI2+dvJvXTt7FtJS+LPt5OvVBY383KEoUlFaGzSz5wqb5ubC0WSsyG3PfZUbKnXzw8wOsKX6EdWUT+NI+nq8cY1nrGMnikjuJd0Xhld1sr3iTt37+IyuLHmZN0WMszxnPzLSBvJnxMMWNPxv7vUITLrdw8VlzMswnNud+xD+O3cGy3LF8ce5R1pZN4IuKsXzlGM0X1SP4uPJ2jgpraJAcfFb+CJHnbuOz8pF8UT6OL0om8nnRJFblPcrLaXfxxolROHzGd2idq7xIHBEavTQFQwAcLNvMP5Lu5JOcsawpmsRnJROIKnuYtVWjWVP9Vz6q7McRz0pUTSa2Zh6LSgeytOJPfGa/j3UVY1lTMoFPz01kdcEjLM95hNmp/8UHmU+j6MYnlrJyz3UMknHW0IbDW8rLyfexIGs4nxU8zqqi8Xx07gGiKkfyheN+ltnvJEFYGdYOFWlUqjniWcGK8iFElQ1jTek4Pi2awOqCR1iZ9wgfnx3Hs4l9+aHc+BqH2voGRFFqC+JpaEKSjOR2Y84iZqX8majcx1ieN57Xc+/hvXPD+aziAZaX30VGY0yH0/1s00E+KR7KquL7+ezceFbnT2BFzkSW5Uzg7VP38UbKQ3hCdc1aKWoLktHsG06/nbnJ9/H+6VGsyJnIC9l38kreMNaUPsKSkkHsdy26aABMcK3lw4L/5l9FY1mdP56lOeP55Ox4Psh+mOeT7+BAyUZj17O8qiWIKMkUlNoBOFQaw4zkQSw+M5bZp+7in7mPsKnkFVade4DPSsfTJNVeFCSk+lhbPIVl+Q+wMnccS8+OY/GZsXxwZjTTj9/OkqwXACi3O/H5A+dBKhy1lFQac33t2bf5R/KdvJnxFxadnkSyYzuf5j3BssIR/Kt4DBvLp/NF2dOsqXiSNRVPsKbyCeNnxZN8XjaFz4ufJrr4Bf5V8Agr8h5iWc5YPs4ey4enR/P+6YeYnfZn3kh9CAUfqgz2Gtd5kLOFpZTYjUMHH516jmlJA3jjxHCO2XexteBtFpwZyqqC0awo+huLCv7Eu4W38V7x73mvtD/vl/Xl/bJ+vFfye94tuo2F+X/g3dw/szT/b6zIHcMnZ0fz0ZmHWXT6ISKzRvJq5mBeSh5MSeNZyzyyrBggWTlFlNsNssiMKYz9oQe7i/9FmmM/r6bezZKfx7Is5yGW5f+NFYUjWHXuflaXDmN12V+JKhtGVNkwVpX9lZXFw1lRNILl+Q/ySc6DfHRmFIuyRhF5ciRvZ/6NNzPvZ3baIJ5N+AM/1xsfXcg9V47XH2wLMidpFE/9eAcVQg7Lsp7j9fShfHTmIT4+M4rIrKG8ljGAeSf78eaZfszP7sc/z/bln9n9mH+mH29m9eO1jP7MPfF7ZibfxvSE3zP1UD+eiruVxw/cxIT9fRj+764Mje3M6bqjAOQVl+MPhgyQvHPllFQapnkhfgRf5y7haNV3PJvwe945+QDvnnyAf2bcQ0zR22S7fySzbj+Z7n2cdO/jZP1eTtbvI9O9j8y6fWS49pHm3Edq9T6OV+0luXIPRyt2k1C+i/jybzhYupUfSrfjV40wX1zhQNN0A8RR66bEbjjr5p+Xc9IRz9snJvJ88h94O/N+3s64j1dS7mJLXuT/v0e/vT6qa93nnVXXdXLOlRtJi6qSWLmL8Yd682rGvcxLG8qbJ4byRuoQXj56L+UNuRcdoDHk5kDJNvaXbuZA2Rb2l21hX9nX7C3byNaCKJKr4pqnbw3+QLBlQDttxn4dPsh4hseP3sjcjP/m5dRBvJYymNdTBjMtvh8rT865KMja0wsZvqsr4/f3ZNyBnjx88CpGxV3BiAM2bt5iY8PPKwz/KKlsG1lDooTgCRJAYPKR/jyb2pcZaQOZdfyPzDn+J145/l/MSfojU364lW05yzuE2F30FU/80JcZSQN5+fifmH38Tmam3MGM1Dt4LOE6pv90DyHFCGLZ+SXtL3pn88rJCR5hbPy1TEq6jqnJv2XGsduZdfwPzD52By8n/5FZSX9g8sGbeDflGU7VHMUTqKMhVM/Z2hMsSZ/JY3G38I/E25l77I/MOv4HZhy/nRkptzE1+Rbu+beNhMrvjLEKSi+cj0T+8AaPZfTi2eQ/8Gj89fz96C3MSB7AjOTfMzPpNmYn3c7MowN4/IdrmXKoPy8l3MtLP/2Fpw7fxiMHr+HFxH7MTrqNmUm/56XkAbyY3I/pyb/jr/tsRJ542hqnOGydaRdkxv6J/DXBxvflX/Fd0Rru2W3jmYTrmZnUnxlJ/ZhxtB+zjg5g1tH+vJBwM1Pjr+fZ+Ot5PuFmZiX2Y9ZR43kvJfXlpeR+PJ90M3/da2Nm4gME5MZ2c5F2QV5OeYA/7rZxrOYgANE/f8S933ViTFxXZiX1ZfbRvsxK7MusxFuZnXgrs8JkZuKtzEi8lZlHf8espL48Gd+Lu3fbeDVpLA1BY+kvc7T7ZTktQUQlyLQjg/nzv20cyo+zrsdX7OKR/bcybLeNp368hpd+uok5ib9lbuKtzfI75ib+jtmJv2PGT7fwfMJveOj7zty/O4JPs+YjKsYUdTc04Wloav/YRusLz/04lAeTIsgsPENewfnc0is1EH32Qx47MICH913F+O//F+O/t/H4wW7877gIHtnfhXHfd2Hs91cyZl9v3k19lgLPaev15TV1NDR6Oz4/0vrC26ceYVhcL45X/GB4d2Eljf7Q+cJI9pHqiGPVqVeZd+wRZicOZ0bCvbyS9DAfpD3PnnNfUuO3ny9NVI2T+eVI8oVPGrUB2ZsfzX1HehJTtMK6FgyJZOYW0+gXf1EIz8wro9LhvKTn2lrugkMoFOS5n/7C0APXYK8tb3GepMrh5HB8Cmknz5JbXEpBSQVlFbVU2N0UlVWRW1RK1s95/JCQzMkzPyPLMpqm4ff7CQQChEIhJElCURQ0TcPsVOm6fn6tCT+oUOkq4bGE27n/qzv4KeMIwVCQQCBAbV0ttXW1VFRWkJ19lrS0DJKSj5F4NInk5OOcPHmK/Px8amtrcbvd1NTU4HQ6cbvdNDU1WTCyLKOqaguYDmvfgNzE4bIYdpWv4UT5EezuMkQl9B877PT/DQC7cLwx8LR3hQAAAABJRU5ErkJggg==) no-repeat;padding-left:40px}
+        .browser .browser-firefox{background-position:0 -34px}
+        .browser .browser-ie{background-position:0 -68px;margin-left:0px}
+        .browser .browser-360{background-position:0 -170px;margin-left: -27px}
+    </style>
+</head>
+<body style="margin-top:50px">
+<h1>璇峰崌绾ф偍鐨勬祻瑙堝櫒锛屼互渚挎垜浠洿濂界殑涓烘偍鎻愪緵鏈嶅姟锛�</h1>
+<p>鎮ㄦ鍦ㄤ娇鐢� Internet Explorer 鐨勬棭鏈熺増鏈紙IE11浠ヤ笅鐗堟湰鎴栦娇鐢ㄨ鍐呮牳鐨勬祻瑙堝櫒锛夈�傝繖鎰忓懗鐫�鍦ㄥ崌绾ф祻瑙堝櫒鍓嶏紝鎮ㄥ皢鏃犳硶璁块棶姝ょ綉绔欍��</p>
+<hr>
+<h2>璇锋敞鎰忥細寰蒋鍏徃瀵筗indows XP 鍙� Internet Explorer 鏃╂湡鐗堟湰鐨勬敮鎸佸凡缁忕粨鏉�</h2>
+<p>鑷� 2016 骞� 1 鏈� 12 鏃ヨ捣锛孧icrosoft 涓嶅啀涓� IE 11 浠ヤ笅鐗堟湰鎻愪緵鐩稿簲鏀寔鍜屾洿鏂般�傛病鏈夊叧閿殑娴忚鍣ㄥ畨鍏ㄦ洿鏂帮紝鎮ㄧ殑鐢佃剳鍙兘鏄撳彈鏈夊鐥呮瘨銆侀棿璋嶈蒋浠跺拰鍏朵粬鎭舵剰杞欢鐨勬敾鍑伙紝瀹冧滑鍙互绐冨彇鎴栨崯瀹虫偍鐨勪笟鍔℃暟鎹拰淇℃伅銆傝鍙傞槄 <a href="https://www.microsoft.com/zh-cn/WindowsForBusiness/End-of-IE-support">寰蒋瀵� Internet Explorer 鏃╂湡鐗堟湰鐨勬敮鎸佸皢浜� 2016 骞� 1 鏈� 12 鏃ョ粨鏉熺殑璇存槑</a> 銆�</p>
+<hr>
+<h2>鎮ㄥ彲浠ラ�夋嫨鏇村厛杩涚殑娴忚鍣�</h2>
+<p>鎺ㄨ崘浣跨敤浠ヤ笅娴忚鍣ㄧ殑鏈�鏂扮増鏈�傚鏋滄偍鐨勭數鑴戝凡鏈変互涓嬫祻瑙堝櫒鐨勬渶鏂扮増鏈垯鐩存帴浣跨敤璇ユ祻瑙堝櫒璁块棶鍗冲彲銆�</p>
+<ul class="browser">
+    <li class="browser-chrome"><a href="https://www.google.cn/chrome/browser/desktop/index.html?hl=zh-CN&standalone=1"> 璋锋瓕娴忚鍣�<span>Google Chrome</span></a></li>
+    <li class="browser-firefox"><a href="https://www.mozilla.org/zh-CN/firefox/new/"> 鐏嫄娴忚鍣�<span>Mozilla Firefox</span></a></li>
+    <li class="browser-ie"><a href="https://windows.microsoft.com/zh-cn/internet-explorer/download-ie"> IE 11 娴忚鍣�<span>Internet Explorer</span></a></li>
+    <li class="browser-360"><a href="http://se.360.cn/"> 360瀹夊叏娴忚鍣�<span>360 Chrome</span></a></li>
+    <div class="clean"></div>
+</ul>
+<hr>
+</body>
+</html>
\ No newline at end of file
diff --git a/jcdm-ui/public/index.html b/jcdm-ui/public/index.html
new file mode 100644
index 0000000..925455c
--- /dev/null
+++ b/jcdm-ui/public/index.html
@@ -0,0 +1,208 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+    <meta name="renderer" content="webkit">
+    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
+    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
+    <title><%= webpackConfig.name %></title>
+    <!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]-->
+	  <style>
+    html,
+    body,
+    #app {
+      height: 100%;
+      margin: 0px;
+      padding: 0px;
+    }
+    .chromeframe {
+      margin: 0.2em 0;
+      background: #ccc;
+      color: #000;
+      padding: 0.2em 0;
+    }
+
+    #loader-wrapper {
+      position: fixed;
+      top: 0;
+      left: 0;
+      width: 100%;
+      height: 100%;
+      z-index: 999999;
+    }
+
+    #loader {
+      display: block;
+      position: relative;
+      left: 50%;
+      top: 50%;
+      width: 150px;
+      height: 150px;
+      margin: -75px 0 0 -75px;
+      border-radius: 50%;
+      border: 3px solid transparent;
+      border-top-color: #FFF;
+      -webkit-animation: spin 2s linear infinite;
+      -ms-animation: spin 2s linear infinite;
+      -moz-animation: spin 2s linear infinite;
+      -o-animation: spin 2s linear infinite;
+      animation: spin 2s linear infinite;
+      z-index: 1001;
+    }
+
+    #loader:before {
+      content: "";
+      position: absolute;
+      top: 5px;
+      left: 5px;
+      right: 5px;
+      bottom: 5px;
+      border-radius: 50%;
+      border: 3px solid transparent;
+      border-top-color: #FFF;
+      -webkit-animation: spin 3s linear infinite;
+      -moz-animation: spin 3s linear infinite;
+      -o-animation: spin 3s linear infinite;
+      -ms-animation: spin 3s linear infinite;
+      animation: spin 3s linear infinite;
+    }
+
+    #loader:after {
+      content: "";
+      position: absolute;
+      top: 15px;
+      left: 15px;
+      right: 15px;
+      bottom: 15px;
+      border-radius: 50%;
+      border: 3px solid transparent;
+      border-top-color: #FFF;
+      -moz-animation: spin 1.5s linear infinite;
+      -o-animation: spin 1.5s linear infinite;
+      -ms-animation: spin 1.5s linear infinite;
+      -webkit-animation: spin 1.5s linear infinite;
+      animation: spin 1.5s linear infinite;
+    }
+
+
+    @-webkit-keyframes spin {
+      0% {
+        -webkit-transform: rotate(0deg);
+        -ms-transform: rotate(0deg);
+        transform: rotate(0deg);
+      }
+      100% {
+        -webkit-transform: rotate(360deg);
+        -ms-transform: rotate(360deg);
+        transform: rotate(360deg);
+      }
+    }
+
+    @keyframes spin {
+      0% {
+        -webkit-transform: rotate(0deg);
+        -ms-transform: rotate(0deg);
+        transform: rotate(0deg);
+      }
+      100% {
+        -webkit-transform: rotate(360deg);
+        -ms-transform: rotate(360deg);
+        transform: rotate(360deg);
+      }
+    }
+
+
+    #loader-wrapper .loader-section {
+      position: fixed;
+      top: 0;
+      width: 51%;
+      height: 100%;
+      background: #7171C6;
+      z-index: 1000;
+      -webkit-transform: translateX(0);
+      -ms-transform: translateX(0);
+      transform: translateX(0);
+    }
+
+    #loader-wrapper .loader-section.section-left {
+      left: 0;
+    }
+
+    #loader-wrapper .loader-section.section-right {
+      right: 0;
+    }
+
+
+    .loaded #loader-wrapper .loader-section.section-left {
+      -webkit-transform: translateX(-100%);
+      -ms-transform: translateX(-100%);
+      transform: translateX(-100%);
+      -webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
+      transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
+    }
+
+    .loaded #loader-wrapper .loader-section.section-right {
+      -webkit-transform: translateX(100%);
+      -ms-transform: translateX(100%);
+      transform: translateX(100%);
+      -webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
+      transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
+    }
+
+    .loaded #loader {
+      opacity: 0;
+      -webkit-transition: all 0.3s ease-out;
+      transition: all 0.3s ease-out;
+    }
+
+    .loaded #loader-wrapper {
+      visibility: hidden;
+      -webkit-transform: translateY(-100%);
+      -ms-transform: translateY(-100%);
+      transform: translateY(-100%);
+      -webkit-transition: all 0.3s 1s ease-out;
+      transition: all 0.3s 1s ease-out;
+    }
+
+    .no-js #loader-wrapper {
+      display: none;
+    }
+
+    .no-js h1 {
+      color: #222222;
+    }
+
+    #loader-wrapper .load_title {
+      font-family: 'Open Sans';
+      color: #FFF;
+      font-size: 19px;
+      width: 100%;
+      text-align: center;
+      z-index: 9999999999999;
+      position: absolute;
+      top: 60%;
+      opacity: 1;
+      line-height: 30px;
+    }
+
+    #loader-wrapper .load_title span {
+      font-weight: normal;
+      font-style: italic;
+      font-size: 13px;
+      color: #FFF;
+      opacity: 0.5;
+    }
+  </style>
+  </head>
+  <body>
+    <div id="app">
+	    <div id="loader-wrapper">
+		    <div id="loader"></div>
+		    <div class="loader-section section-left"></div>
+		    <div class="loader-section section-right"></div>
+		    <div class="load_title">姝e湪鍔犺浇绯荤粺璧勬簮锛岃鑰愬績绛夊緟</div>
+        </div>
+	</div>
+  </body>
+</html>
diff --git a/jcdm-ui/public/robots.txt b/jcdm-ui/public/robots.txt
new file mode 100644
index 0000000..77470cb
--- /dev/null
+++ b/jcdm-ui/public/robots.txt
@@ -0,0 +1,2 @@
+User-agent: *
+Disallow: /
\ No newline at end of file
diff --git a/jcdm-ui/src/App.vue b/jcdm-ui/src/App.vue
new file mode 100644
index 0000000..b92ea37
--- /dev/null
+++ b/jcdm-ui/src/App.vue
@@ -0,0 +1,28 @@
+<template>
+  <div id="app">
+    <router-view />
+    <theme-picker />
+  </div>
+</template>
+
+<script>
+import ThemePicker from "@/components/ThemePicker";
+
+export default {
+  name: "App",
+  components: { ThemePicker },
+  metaInfo() {
+    return {
+      title: this.$store.state.settings.dynamicTitle && this.$store.state.settings.title,
+      titleTemplate: title => {
+        return title ? `${title} - ${process.env.VUE_APP_TITLE}` : process.env.VUE_APP_TITLE
+      }
+    }
+  }
+};
+</script>
+<style scoped>
+#app .theme-picker {
+  display: none;
+}
+</style>
diff --git a/jcdm-ui/src/api/login.js b/jcdm-ui/src/api/login.js
new file mode 100644
index 0000000..7b7388f
--- /dev/null
+++ b/jcdm-ui/src/api/login.js
@@ -0,0 +1,60 @@
+import request from '@/utils/request'
+
+// 鐧诲綍鏂规硶
+export function login(username, password, code, uuid) {
+  const data = {
+    username,
+    password,
+    code,
+    uuid
+  }
+  return request({
+    url: '/login',
+    headers: {
+      isToken: false,
+      repeatSubmit: false
+    },
+    method: 'post',
+    data: data
+  })
+}
+
+// 娉ㄥ唽鏂规硶
+export function register(data) {
+  return request({
+    url: '/register',
+    headers: {
+      isToken: false
+    },
+    method: 'post',
+    data: data
+  })
+}
+
+// 鑾峰彇鐢ㄦ埛璇︾粏淇℃伅
+export function getInfo() {
+  return request({
+    url: '/getInfo',
+    method: 'get'
+  })
+}
+
+// 閫�鍑烘柟娉�
+export function logout() {
+  return request({
+    url: '/logout',
+    method: 'post'
+  })
+}
+
+// 鑾峰彇楠岃瘉鐮�
+export function getCodeImg() {
+  return request({
+    url: '/captchaImage',
+    headers: {
+      isToken: false
+    },
+    method: 'get',
+    timeout: 20000
+  })
+}
\ No newline at end of file
diff --git a/jcdm-ui/src/api/main/bs/ProductBom/ProductBom.js b/jcdm-ui/src/api/main/bs/ProductBom/ProductBom.js
new file mode 100644
index 0000000..ee39917
--- /dev/null
+++ b/jcdm-ui/src/api/main/bs/ProductBom/ProductBom.js
@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 鏌ヨ鍩虹BOM鍒楄〃
+export function listProductBom(query) {
+  return request({
+    url: '/bs/ProductBom/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ鍩虹BOM璇︾粏
+export function getProductBom(id) {
+  return request({
+    url: '/bs/ProductBom/' + id,
+    method: 'get'
+  })
+}
+
+// 鏂板鍩虹BOM
+export function addProductBom(data) {
+  return request({
+    url: '/bs/ProductBom',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼鍩虹BOM
+export function updateProductBom(data) {
+  return request({
+    url: '/bs/ProductBom',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎鍩虹BOM
+export function delProductBom(id) {
+  return request({
+    url: '/bs/ProductBom/' + id,
+    method: 'delete'
+  })
+}
diff --git a/jcdm-ui/src/api/main/bs/ProductBomChild/ProductBomChild.js b/jcdm-ui/src/api/main/bs/ProductBomChild/ProductBomChild.js
new file mode 100644
index 0000000..77c64f3
--- /dev/null
+++ b/jcdm-ui/src/api/main/bs/ProductBomChild/ProductBomChild.js
@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 鏌ヨ鍩虹BOM瀛愪俊鎭垪琛�
+export function listProductBomChild(query) {
+  return request({
+    url: '/bs/ProductBomChild/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ鍩虹BOM瀛愪俊鎭缁�
+export function getProductBomChild(id) {
+  return request({
+    url: '/bs/ProductBomChild/' + id,
+    method: 'get'
+  })
+}
+
+// 鏂板鍩虹BOM瀛愪俊鎭�
+export function addProductBomChild(data) {
+  return request({
+    url: '/bs/ProductBomChild',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼鍩虹BOM瀛愪俊鎭�
+export function updateProductBomChild(data) {
+  return request({
+    url: '/bs/ProductBomChild',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎鍩虹BOM瀛愪俊鎭�
+export function delProductBomChild(id) {
+  return request({
+    url: '/bs/ProductBomChild/' + id,
+    method: 'delete'
+  })
+}
diff --git a/jcdm-ui/src/api/main/bs/beatSetting/beatSetting.js b/jcdm-ui/src/api/main/bs/beatSetting/beatSetting.js
new file mode 100644
index 0000000..fd20dac
--- /dev/null
+++ b/jcdm-ui/src/api/main/bs/beatSetting/beatSetting.js
@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 鏌ヨ鑺傛媿璁剧疆鍒楄〃
+export function listBeatSetting(query) {
+  return request({
+    url: '/bs/beatSetting/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ鑺傛媿璁剧疆璇︾粏
+export function getBeatSetting(id) {
+  return request({
+    url: '/bs/beatSetting/' + id,
+    method: 'get'
+  })
+}
+
+// 鏂板鑺傛媿璁剧疆
+export function addBeatSetting(data) {
+  return request({
+    url: '/bs/beatSetting',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼鑺傛媿璁剧疆
+export function updateBeatSetting(data) {
+  return request({
+    url: '/bs/beatSetting',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎鑺傛媿璁剧疆
+export function delBeatSetting(id) {
+  return request({
+    url: '/bs/beatSetting/' + id,
+    method: 'delete'
+  })
+}
diff --git a/jcdm-ui/src/api/main/bs/formula/formula.js b/jcdm-ui/src/api/main/bs/formula/formula.js
new file mode 100644
index 0000000..33ea48c
--- /dev/null
+++ b/jcdm-ui/src/api/main/bs/formula/formula.js
@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 鏌ヨ閰嶆柟閰嶇疆鍒楄〃
+export function listFormula(query) {
+  return request({
+    url: '/bs/formula/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ閰嶆柟閰嶇疆璇︾粏
+export function getFormula(id) {
+  return request({
+    url: '/bs/formula/' + id,
+    method: 'get'
+  })
+}
+
+// 鏂板閰嶆柟閰嶇疆
+export function addFormula(data) {
+  return request({
+    url: '/bs/formula',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼閰嶆柟閰嶇疆
+export function updateFormula(data) {
+  return request({
+    url: '/bs/formula',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎閰嶆柟閰嶇疆
+export function delFormula(id) {
+  return request({
+    url: '/bs/formula/' + id,
+    method: 'delete'
+  })
+}
diff --git a/jcdm-ui/src/api/main/bs/formulaChild/formulaChild.js b/jcdm-ui/src/api/main/bs/formulaChild/formulaChild.js
new file mode 100644
index 0000000..ff841b7
--- /dev/null
+++ b/jcdm-ui/src/api/main/bs/formulaChild/formulaChild.js
@@ -0,0 +1,73 @@
+import request from '@/utils/request'
+
+// 鏌ヨ閰嶆柟閰嶇疆瀛愪俊鎭垪琛�
+export function listFormulaChild(query) {
+  return request({
+    url: '/bs/formulaChild/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ閰嶆柟閰嶇疆瀛愪俊鎭垪琛�
+export function releaseCheck(query) {
+  return request({
+    url: '/bs/formulaChild/releaseCheck',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ閰嶆柟閰嶇疆瀛愪俊鎭垪琛�
+export function updateResults(query) {
+  return request({
+    url: '/bs/formulaChild/updateResults',
+    method: 'get',
+    params: query
+
+  })
+}
+
+// 鏌ヨ閰嶆柟閰嶇疆瀛愪俊鎭垪琛�
+export function workpieceRelease(query) {
+  return request({
+    url: '/bs/formulaChild/workpieceRelease',
+    method: 'get',
+    params: query
+
+  })
+}
+
+// 鏌ヨ閰嶆柟閰嶇疆瀛愪俊鎭缁�
+export function getFormulaChild(id) {
+  return request({
+    url: '/bs/formulaChild/' + id,
+    method: 'get'
+  })
+}
+
+// 鏂板閰嶆柟閰嶇疆瀛愪俊鎭�
+export function addFormulaChild(data) {
+  return request({
+    url: '/bs/formulaChild',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼閰嶆柟閰嶇疆瀛愪俊鎭�
+export function updateFormulaChild(data) {
+  return request({
+    url: '/bs/formulaChild',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎閰嶆柟閰嶇疆瀛愪俊鎭�
+export function delFormulaChild(id) {
+  return request({
+    url: '/bs/formulaChild/' + id,
+    method: 'delete'
+  })
+}
diff --git a/jcdm-ui/src/api/main/bs/lineInfo/lineInfo.js b/jcdm-ui/src/api/main/bs/lineInfo/lineInfo.js
new file mode 100644
index 0000000..b2f634f
--- /dev/null
+++ b/jcdm-ui/src/api/main/bs/lineInfo/lineInfo.js
@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 鏌ヨ浜х嚎淇℃伅鍒楄〃
+export function listLineInfo(query) {
+  return request({
+    url: '/bs/lineInfo/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ浜х嚎淇℃伅璇︾粏
+export function getLineInfo(id) {
+  return request({
+    url: '/bs/lineInfo/' + id,
+    method: 'get'
+  })
+}
+
+// 鏂板浜х嚎淇℃伅
+export function addLineInfo(data) {
+  return request({
+    url: '/bs/lineInfo',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼浜х嚎淇℃伅
+export function updateLineInfo(data) {
+  return request({
+    url: '/bs/lineInfo',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎浜х嚎淇℃伅
+export function delLineInfo(id) {
+  return request({
+    url: '/bs/lineInfo/' + id,
+    method: 'delete'
+  })
+}
diff --git a/jcdm-ui/src/api/main/bs/material/material.js b/jcdm-ui/src/api/main/bs/material/material.js
new file mode 100644
index 0000000..bf10392
--- /dev/null
+++ b/jcdm-ui/src/api/main/bs/material/material.js
@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 鏌ヨ鐗╂枡淇℃伅鍒楄〃
+export function listMaterial(query) {
+  return request({
+    url: '/bs/material/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ鐗╂枡淇℃伅璇︾粏
+export function getMaterial(id) {
+  return request({
+    url: '/bs/material/' + id,
+    method: 'get'
+  })
+}
+
+// 鏂板鐗╂枡淇℃伅
+export function addMaterial(data) {
+  return request({
+    url: '/bs/material',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼鐗╂枡淇℃伅
+export function updateMaterial(data) {
+  return request({
+    url: '/bs/material',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎鐗╂枡淇℃伅
+export function delMaterial(id) {
+  return request({
+    url: '/bs/material/' + id,
+    method: 'delete'
+  })
+}
diff --git a/jcdm-ui/src/api/main/bs/processFile/processFile.js b/jcdm-ui/src/api/main/bs/processFile/processFile.js
new file mode 100644
index 0000000..f8ec451
--- /dev/null
+++ b/jcdm-ui/src/api/main/bs/processFile/processFile.js
@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 鏌ヨ宸ヨ壓鏂囨。鍒楄〃
+export function listProcessFile(query) {
+  return request({
+    url: '/bs/processFile/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ宸ヨ壓鏂囨。璇︾粏
+export function getProcessFile(id) {
+  return request({
+    url: '/bs/processFile/' + id,
+    method: 'get'
+  })
+}
+
+// 鏂板宸ヨ壓鏂囨。
+export function addProcessFile(data) {
+  return request({
+    url: '/bs/processFile',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼宸ヨ壓鏂囨。
+export function updateProcessFile(data) {
+  return request({
+    url: '/bs/processFile',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎宸ヨ壓鏂囨。
+export function delProcessFile(id) {
+  return request({
+    url: '/bs/processFile/' + id,
+    method: 'delete'
+  })
+}
diff --git a/jcdm-ui/src/api/main/bs/processes/processes.js b/jcdm-ui/src/api/main/bs/processes/processes.js
new file mode 100644
index 0000000..f9e93e4
--- /dev/null
+++ b/jcdm-ui/src/api/main/bs/processes/processes.js
@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 鏌ヨ宸ュ簭淇℃伅鍒楄〃
+export function listProcesses(query) {
+  return request({
+    url: '/bs/processes/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ宸ュ簭淇℃伅璇︾粏
+export function getProcesses(id) {
+  return request({
+    url: '/bs/processes/' + id,
+    method: 'get'
+  })
+}
+
+// 鏂板宸ュ簭淇℃伅
+export function addProcesses(data) {
+  return request({
+    url: '/bs/processes',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼宸ュ簭淇℃伅
+export function updateProcesses(data) {
+  return request({
+    url: '/bs/processes',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎宸ュ簭淇℃伅
+export function delProcesses(id) {
+  return request({
+    url: '/bs/processes/' + id,
+    method: 'delete'
+  })
+}
diff --git a/jcdm-ui/src/api/main/bs/technologyRoute/technologyRoute.js b/jcdm-ui/src/api/main/bs/technologyRoute/technologyRoute.js
new file mode 100644
index 0000000..9a104dd
--- /dev/null
+++ b/jcdm-ui/src/api/main/bs/technologyRoute/technologyRoute.js
@@ -0,0 +1,52 @@
+import request from '@/utils/request'
+
+// 鏌ヨ宸ヨ壓娴佺▼鍒楄〃
+export function listTechnologyRoute(query) {
+  return request({
+    url: '/bs/technologyRoute/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ宸ヨ壓娴佺▼璇︾粏
+export function getTechnologyRoute(id) {
+  return request({
+    url: '/bs/technologyRoute/' + id,
+    method: 'get'
+  })
+}
+
+// 鏂板宸ヨ壓娴佺▼
+export function addTechnologyRoute(data) {
+  return request({
+    url: '/bs/technologyRoute',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼宸ヨ壓娴佺▼
+export function updateTechnologyRoute(data) {
+  return request({
+    url: '/bs/technologyRoute',
+    method: 'put',
+    data: data
+  })
+}
+
+export function updateTechnologyRouteAndChild(data) {
+  return request({
+    url: '/bs/technologyRoute/technologyRouteAndChild',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎宸ヨ壓娴佺▼
+export function delTechnologyRoute(id) {
+  return request({
+    url: '/bs/technologyRoute/' + id,
+    method: 'delete'
+  })
+}
diff --git a/jcdm-ui/src/api/main/bs/technologyRouteChild/technologyRouteChild.js b/jcdm-ui/src/api/main/bs/technologyRouteChild/technologyRouteChild.js
new file mode 100644
index 0000000..5ba5b06
--- /dev/null
+++ b/jcdm-ui/src/api/main/bs/technologyRouteChild/technologyRouteChild.js
@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 鏌ヨ宸ヨ壓璺嚎瀛愪俊鎭垪琛�
+export function listTechnologyRouteChild(query) {
+  return request({
+    url: '/bs/technologyRouteChild/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ宸ヨ壓璺嚎瀛愪俊鎭缁�
+export function getTechnologyRouteChild(id) {
+  return request({
+    url: '/bs/technologyRouteChild/' + id,
+    method: 'get'
+  })
+}
+
+// 鏂板宸ヨ壓璺嚎瀛愪俊鎭�
+export function addTechnologyRouteChild(data) {
+  return request({
+    url: '/bs/technologyRouteChild',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼宸ヨ壓璺嚎瀛愪俊鎭�
+export function updateTechnologyRouteChild(data) {
+  return request({
+    url: '/bs/technologyRouteChild',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎宸ヨ壓璺嚎瀛愪俊鎭�
+export function delTechnologyRouteChild(id) {
+  return request({
+    url: '/bs/technologyRouteChild/' + id,
+    method: 'delete'
+  })
+}
diff --git a/jcdm-ui/src/api/main/bs/workshop/workshop.js b/jcdm-ui/src/api/main/bs/workshop/workshop.js
new file mode 100644
index 0000000..f062146
--- /dev/null
+++ b/jcdm-ui/src/api/main/bs/workshop/workshop.js
@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 鏌ヨ杞﹂棿淇℃伅鍒楄〃
+export function listWorkshop(query) {
+  return request({
+    url: '/bs/workshop/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ杞﹂棿淇℃伅璇︾粏
+export function getWorkshop(id) {
+  return request({
+    url: '/bs/workshop/' + id,
+    method: 'get'
+  })
+}
+
+// 鏂板杞﹂棿淇℃伅
+export function addWorkshop(data) {
+  return request({
+    url: '/bs/workshop',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼杞﹂棿淇℃伅
+export function updateWorkshop(data) {
+  return request({
+    url: '/bs/workshop',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎杞﹂棿淇℃伅
+export function delWorkshop(id) {
+  return request({
+    url: '/bs/workshop/' + id,
+    method: 'delete'
+  })
+}
diff --git a/jcdm-ui/src/api/main/da/collectionParamConf/collectionParamConf.js b/jcdm-ui/src/api/main/da/collectionParamConf/collectionParamConf.js
new file mode 100644
index 0000000..8f48767
--- /dev/null
+++ b/jcdm-ui/src/api/main/da/collectionParamConf/collectionParamConf.js
@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 鏌ヨ閲囬泦鍙傛暟閰嶇疆鍒楄〃
+export function listCollectionParamConf(query) {
+  return request({
+    url: '/da/collectionParamConf/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ閲囬泦鍙傛暟閰嶇疆璇︾粏
+export function getCollectionParamConf(id) {
+  return request({
+    url: '/da/collectionParamConf/' + id,
+    method: 'get'
+  })
+}
+
+// 鏂板閲囬泦鍙傛暟閰嶇疆
+export function addCollectionParamConf(data) {
+  return request({
+    url: '/da/collectionParamConf',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼閲囬泦鍙傛暟閰嶇疆
+export function updateCollectionParamConf(data) {
+  return request({
+    url: '/da/collectionParamConf',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎閲囬泦鍙傛暟閰嶇疆
+export function delCollectionParamConf(id) {
+  return request({
+    url: '/da/collectionParamConf/' + id,
+    method: 'delete'
+  })
+}
diff --git a/jcdm-ui/src/api/main/da/opcuaconfig/opcuaconfig.js b/jcdm-ui/src/api/main/da/opcuaconfig/opcuaconfig.js
new file mode 100644
index 0000000..5bb1420
--- /dev/null
+++ b/jcdm-ui/src/api/main/da/opcuaconfig/opcuaconfig.js
@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 鏌ヨOPCUA鍙傛暟璁剧疆鍒楄〃
+export function listOpcuaconfig(query) {
+  return request({
+    url: '/da/opcuaconfig/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨOPCUA鍙傛暟璁剧疆璇︾粏
+export function getOpcuaconfig(id) {
+  return request({
+    url: '/da/opcuaconfig/' + id,
+    method: 'get'
+  })
+}
+
+// 鏂板OPCUA鍙傛暟璁剧疆
+export function addOpcuaconfig(data) {
+  return request({
+    url: '/da/opcuaconfig',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼OPCUA鍙傛暟璁剧疆
+export function updateOpcuaconfig(data) {
+  return request({
+    url: '/da/opcuaconfig',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎OPCUA鍙傛暟璁剧疆
+export function delOpcuaconfig(id) {
+  return request({
+    url: '/da/opcuaconfig/' + id,
+    method: 'delete'
+  })
+}
diff --git a/jcdm-ui/src/api/main/da/paramCollection/paramCollection.js b/jcdm-ui/src/api/main/da/paramCollection/paramCollection.js
new file mode 100644
index 0000000..2983328
--- /dev/null
+++ b/jcdm-ui/src/api/main/da/paramCollection/paramCollection.js
@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 鏌ヨ璁惧浜у搧杩囩▼鍙傛暟閲囬泦鍒楄〃
+export function listParamCollection(query) {
+  return request({
+    url: '/main/paramCollection/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ璁惧浜у搧杩囩▼鍙傛暟閲囬泦璇︾粏
+export function getParamCollection(id) {
+  return request({
+    url: '/main/paramCollection/' + id,
+    method: 'get'
+  })
+}
+
+// 鏂板璁惧浜у搧杩囩▼鍙傛暟閲囬泦
+export function addParamCollection(data) {
+  return request({
+    url: '/main/paramCollection',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼璁惧浜у搧杩囩▼鍙傛暟閲囬泦
+export function updateParamCollection(data) {
+  return request({
+    url: '/main/paramCollection',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎璁惧浜у搧杩囩▼鍙傛暟閲囬泦
+export function delParamCollection(id) {
+  return request({
+    url: '/main/paramCollection/' + id,
+    method: 'delete'
+  })
+}
diff --git a/jcdm-ui/src/api/main/da/passingStationCollection/passingStationCollection.js b/jcdm-ui/src/api/main/da/passingStationCollection/passingStationCollection.js
new file mode 100644
index 0000000..6d6b40a
--- /dev/null
+++ b/jcdm-ui/src/api/main/da/passingStationCollection/passingStationCollection.js
@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 鏌ヨ浜у搧杩囩珯閲囬泦鍒楄〃
+export function listPassingStationCollection(query) {
+  return request({
+    url: '/da/passingStationCollection/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ浜у搧杩囩珯閲囬泦璇︾粏
+export function getPassingStationCollection(id) {
+  return request({
+    url: '/da/passingStationCollection/' + id,
+    method: 'get'
+  })
+}
+
+// 鏂板浜у搧杩囩珯閲囬泦
+export function addPassingStationCollection(data) {
+  return request({
+    url: '/da/passingStationCollection',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼浜у搧杩囩珯閲囬泦
+export function updatePassingStationCollection(data) {
+  return request({
+    url: '/da/passingStationCollection',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎浜у搧杩囩珯閲囬泦
+export function delPassingStationCollection(id) {
+  return request({
+    url: '/da/passingStationCollection/' + id,
+    method: 'delete'
+  })
+}
diff --git a/jcdm-ui/src/api/main/em/equipmentAlarm/equipmentAlarm.js b/jcdm-ui/src/api/main/em/equipmentAlarm/equipmentAlarm.js
new file mode 100644
index 0000000..da5d2cd
--- /dev/null
+++ b/jcdm-ui/src/api/main/em/equipmentAlarm/equipmentAlarm.js
@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 鏌ヨ璁惧鎶ヨ鍒楄〃
+export function listEquipmentAlarm(query) {
+  return request({
+    url: '/em/equipmentAlarm/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ璁惧鎶ヨ璇︾粏
+export function getEquipmentAlarm(id) {
+  return request({
+    url: '/em/equipmentAlarm/' + id,
+    method: 'get'
+  })
+}
+
+// 鏂板璁惧鎶ヨ
+export function addEquipmentAlarm(data) {
+  return request({
+    url: '/em/equipmentAlarm',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼璁惧鎶ヨ
+export function updateEquipmentAlarm(data) {
+  return request({
+    url: '/em/equipmentAlarm',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎璁惧鎶ヨ
+export function delEquipmentAlarm(id) {
+  return request({
+    url: '/em/equipmentAlarm/' + id,
+    method: 'delete'
+  })
+}
diff --git a/jcdm-ui/src/api/main/em/equipmentArchives/equipmentArchives.js b/jcdm-ui/src/api/main/em/equipmentArchives/equipmentArchives.js
new file mode 100644
index 0000000..36fdd13
--- /dev/null
+++ b/jcdm-ui/src/api/main/em/equipmentArchives/equipmentArchives.js
@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 鏌ヨ璁惧妗f鍒楄〃
+export function listEquipmentArchives(query) {
+  return request({
+    url: '/em/equipmentArchives/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ璁惧妗f璇︾粏
+export function getEquipmentArchives(id) {
+  return request({
+    url: '/em/equipmentArchives/' + id,
+    method: 'get'
+  })
+}
+
+// 鏂板璁惧妗f
+export function addEquipmentArchives(data) {
+  return request({
+    url: '/em/equipmentArchives',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼璁惧妗f
+export function updateEquipmentArchives(data) {
+  return request({
+    url: '/em/equipmentArchives',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎璁惧妗f
+export function delEquipmentArchives(id) {
+  return request({
+    url: '/em/equipmentArchives/' + id,
+    method: 'delete'
+  })
+}
diff --git a/jcdm-ui/src/api/main/em/equipmentStatus/equipmentStatus.js b/jcdm-ui/src/api/main/em/equipmentStatus/equipmentStatus.js
new file mode 100644
index 0000000..1ce52a6
--- /dev/null
+++ b/jcdm-ui/src/api/main/em/equipmentStatus/equipmentStatus.js
@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 鏌ヨ璁惧鐘舵�佸垪琛�
+export function listEquipmentStatus(query) {
+  return request({
+    url: '/em/equipmentStatus/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ璁惧鐘舵�佽缁�
+export function getEquipmentStatus(id) {
+  return request({
+    url: '/em/equipmentStatus/' + id,
+    method: 'get'
+  })
+}
+
+// 鏂板璁惧鐘舵��
+export function addEquipmentStatus(data) {
+  return request({
+    url: '/em/equipmentStatus',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼璁惧鐘舵��
+export function updateEquipmentStatus(data) {
+  return request({
+    url: '/em/equipmentStatus',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎璁惧鐘舵��
+export function delEquipmentStatus(id) {
+  return request({
+    url: '/em/equipmentStatus/' + id,
+    method: 'delete'
+  })
+}
diff --git a/jcdm-ui/src/api/main/om/productionOrde/productionOrde.js b/jcdm-ui/src/api/main/om/productionOrde/productionOrde.js
new file mode 100644
index 0000000..acff9ce
--- /dev/null
+++ b/jcdm-ui/src/api/main/om/productionOrde/productionOrde.js
@@ -0,0 +1,52 @@
+import request from '@/utils/request'
+
+// 鏌ヨ鐢熶骇宸ュ崟鍒楄〃
+export function listProductionOrde(query) {
+  return request({
+    url: '/om/productionOrde/list',
+    method: 'get',
+    params: query
+  })
+}
+
+export function upDownMove(query) {
+  return request({
+    url: '/om/productionOrde/upDownMove',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ鐢熶骇宸ュ崟璇︾粏
+export function getProductionOrde(id) {
+  return request({
+    url: '/om/productionOrde/' + id,
+    method: 'get'
+  })
+}
+
+// 鏂板鐢熶骇宸ュ崟
+export function addProductionOrde(data) {
+  return request({
+    url: '/om/productionOrde',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼鐢熶骇宸ュ崟
+export function updateProductionOrde(data) {
+  return request({
+    url: '/om/productionOrde',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎鐢熶骇宸ュ崟
+export function delProductionOrde(id) {
+  return request({
+    url: '/om/productionOrde/' + id,
+    method: 'delete'
+  })
+}
diff --git a/jcdm-ui/src/api/main/om/workReport/workReport.js b/jcdm-ui/src/api/main/om/workReport/workReport.js
new file mode 100644
index 0000000..168f7a8
--- /dev/null
+++ b/jcdm-ui/src/api/main/om/workReport/workReport.js
@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 鏌ヨ鎶ュ伐璁板綍 琛ㄥ垪琛�
+export function listWorkReport(query) {
+  return request({
+    url: '/om/workReport/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ鎶ュ伐璁板綍 琛ㄨ缁�
+export function getWorkReport(id) {
+  return request({
+    url: '/om/workReport/' + id,
+    method: 'get'
+  })
+}
+
+// 鏂板鎶ュ伐璁板綍 琛�
+export function addWorkReport(data) {
+  return request({
+    url: '/om/workReport',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼鎶ュ伐璁板綍 琛�
+export function updateWorkReport(data) {
+  return request({
+    url: '/om/workReport',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎鎶ュ伐璁板綍 琛�
+export function delWorkReport(id) {
+  return request({
+    url: '/om/workReport/' + id,
+    method: 'delete'
+  })
+}
diff --git a/jcdm-ui/src/api/main/rm/repairData/repairData.js b/jcdm-ui/src/api/main/rm/repairData/repairData.js
new file mode 100644
index 0000000..79c8f64
--- /dev/null
+++ b/jcdm-ui/src/api/main/rm/repairData/repairData.js
@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 鏌ヨ杩斾慨鏁版嵁鍒楄〃
+export function listRepairData(query) {
+  return request({
+    url: '/rm/repairData/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ杩斾慨鏁版嵁璇︾粏
+export function getRepairData(id) {
+  return request({
+    url: '/rm/repairData/' + id,
+    method: 'get'
+  })
+}
+
+// 鏂板杩斾慨鏁版嵁
+export function addRepairData(data) {
+  return request({
+    url: '/rm/repairData',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼杩斾慨鏁版嵁
+export function updateRepairData(data) {
+  return request({
+    url: '/rm/repairData',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎杩斾慨鏁版嵁
+export function delRepairData(id) {
+  return request({
+    url: '/rm/repairData/' + id,
+    method: 'delete'
+  })
+}
diff --git a/jcdm-ui/src/api/main/rm/repairRecord/repairRecord.js b/jcdm-ui/src/api/main/rm/repairRecord/repairRecord.js
new file mode 100644
index 0000000..0083674
--- /dev/null
+++ b/jcdm-ui/src/api/main/rm/repairRecord/repairRecord.js
@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 鏌ヨ杩斾慨璁板綍鍒楄〃
+export function listRepairRecord(query) {
+  return request({
+    url: '/rm/repairRecord/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ杩斾慨璁板綍璇︾粏
+export function getRepairRecord(id) {
+  return request({
+    url: '/rm/repairRecord/' + id,
+    method: 'get'
+  })
+}
+
+// 鏂板杩斾慨璁板綍
+export function addRepairRecord(data) {
+  return request({
+    url: '/rm/repairRecord',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼杩斾慨璁板綍
+export function updateRepairRecord(data) {
+  return request({
+    url: '/rm/repairRecord',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎杩斾慨璁板綍
+export function delRepairRecord(id) {
+  return request({
+    url: '/rm/repairRecord/' + id,
+    method: 'delete'
+  })
+}
diff --git a/jcdm-ui/src/api/main/sc/stationConf.js b/jcdm-ui/src/api/main/sc/stationConf.js
new file mode 100644
index 0000000..f75533e
--- /dev/null
+++ b/jcdm-ui/src/api/main/sc/stationConf.js
@@ -0,0 +1,52 @@
+import request from '@/utils/request'
+
+// 鏌ヨ宸ヤ綅缁堢閰嶇疆鍒楄〃
+export function listStationConf(query) {
+  return request({
+    url: '/sc/stationConf/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨIP
+export function getIpv4() {
+  return request({
+    url: '/sc/stationConf/getIpv4',
+    method: 'get',
+  })
+}
+
+// 鏌ヨ宸ヤ綅缁堢閰嶇疆璇︾粏
+export function getStationConf(id) {
+  return request({
+    url: '/sc/stationConf/' + id,
+    method: 'get'
+  })
+}
+
+// 鏂板宸ヤ綅缁堢閰嶇疆
+export function addStationConf(data) {
+  return request({
+    url: '/sc/stationConf',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼宸ヤ綅缁堢閰嶇疆
+export function updateStationConf(data) {
+  return request({
+    url: '/sc/stationConf',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎宸ヤ綅缁堢閰嶇疆
+export function delStationConf(id) {
+  return request({
+    url: '/sc/stationConf/' + id,
+    method: 'delete'
+  })
+}
diff --git a/jcdm-ui/src/api/menu.js b/jcdm-ui/src/api/menu.js
new file mode 100644
index 0000000..faef101
--- /dev/null
+++ b/jcdm-ui/src/api/menu.js
@@ -0,0 +1,9 @@
+import request from '@/utils/request'
+
+// 鑾峰彇璺敱
+export const getRouters = () => {
+  return request({
+    url: '/getRouters',
+    method: 'get'
+  })
+}
\ No newline at end of file
diff --git a/jcdm-ui/src/api/monitor/cache.js b/jcdm-ui/src/api/monitor/cache.js
new file mode 100644
index 0000000..72c5f6a
--- /dev/null
+++ b/jcdm-ui/src/api/monitor/cache.js
@@ -0,0 +1,57 @@
+import request from '@/utils/request'
+
+// 鏌ヨ缂撳瓨璇︾粏
+export function getCache() {
+  return request({
+    url: '/monitor/cache',
+    method: 'get'
+  })
+}
+
+// 鏌ヨ缂撳瓨鍚嶇О鍒楄〃
+export function listCacheName() {
+  return request({
+    url: '/monitor/cache/getNames',
+    method: 'get'
+  })
+}
+
+// 鏌ヨ缂撳瓨閿悕鍒楄〃
+export function listCacheKey(cacheName) {
+  return request({
+    url: '/monitor/cache/getKeys/' + cacheName,
+    method: 'get'
+  })
+}
+
+// 鏌ヨ缂撳瓨鍐呭
+export function getCacheValue(cacheName, cacheKey) {
+  return request({
+    url: '/monitor/cache/getValue/' + cacheName + '/' + cacheKey,
+    method: 'get'
+  })
+}
+
+// 娓呯悊鎸囧畾鍚嶇О缂撳瓨
+export function clearCacheName(cacheName) {
+  return request({
+    url: '/monitor/cache/clearCacheName/' + cacheName,
+    method: 'delete'
+  })
+}
+
+// 娓呯悊鎸囧畾閿悕缂撳瓨
+export function clearCacheKey(cacheKey) {
+  return request({
+    url: '/monitor/cache/clearCacheKey/' + cacheKey,
+    method: 'delete'
+  })
+}
+
+// 娓呯悊鍏ㄩ儴缂撳瓨
+export function clearCacheAll() {
+  return request({
+    url: '/monitor/cache/clearCacheAll',
+    method: 'delete'
+  })
+}
diff --git a/jcdm-ui/src/api/monitor/job.js b/jcdm-ui/src/api/monitor/job.js
new file mode 100644
index 0000000..3815569
--- /dev/null
+++ b/jcdm-ui/src/api/monitor/job.js
@@ -0,0 +1,71 @@
+import request from '@/utils/request'
+
+// 鏌ヨ瀹氭椂浠诲姟璋冨害鍒楄〃
+export function listJob(query) {
+  return request({
+    url: '/monitor/job/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ瀹氭椂浠诲姟璋冨害璇︾粏
+export function getJob(jobId) {
+  return request({
+    url: '/monitor/job/' + jobId,
+    method: 'get'
+  })
+}
+
+// 鏂板瀹氭椂浠诲姟璋冨害
+export function addJob(data) {
+  return request({
+    url: '/monitor/job',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼瀹氭椂浠诲姟璋冨害
+export function updateJob(data) {
+  return request({
+    url: '/monitor/job',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎瀹氭椂浠诲姟璋冨害
+export function delJob(jobId) {
+  return request({
+    url: '/monitor/job/' + jobId,
+    method: 'delete'
+  })
+}
+
+// 浠诲姟鐘舵�佷慨鏀�
+export function changeJobStatus(jobId, status) {
+  const data = {
+    jobId,
+    status
+  }
+  return request({
+    url: '/monitor/job/changeStatus',
+    method: 'put',
+    data: data
+  })
+}
+
+
+// 瀹氭椂浠诲姟绔嬪嵆鎵ц涓�娆�
+export function runJob(jobId, jobGroup) {
+  const data = {
+    jobId,
+    jobGroup
+  }
+  return request({
+    url: '/monitor/job/run',
+    method: 'put',
+    data: data
+  })
+}
\ No newline at end of file
diff --git a/jcdm-ui/src/api/monitor/jobLog.js b/jcdm-ui/src/api/monitor/jobLog.js
new file mode 100644
index 0000000..6e0be61
--- /dev/null
+++ b/jcdm-ui/src/api/monitor/jobLog.js
@@ -0,0 +1,26 @@
+import request from '@/utils/request'
+
+// 鏌ヨ璋冨害鏃ュ織鍒楄〃
+export function listJobLog(query) {
+  return request({
+    url: '/monitor/jobLog/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鍒犻櫎璋冨害鏃ュ織
+export function delJobLog(jobLogId) {
+  return request({
+    url: '/monitor/jobLog/' + jobLogId,
+    method: 'delete'
+  })
+}
+
+// 娓呯┖璋冨害鏃ュ織
+export function cleanJobLog() {
+  return request({
+    url: '/monitor/jobLog/clean',
+    method: 'delete'
+  })
+}
diff --git a/jcdm-ui/src/api/monitor/logininfor.js b/jcdm-ui/src/api/monitor/logininfor.js
new file mode 100644
index 0000000..4d112b7
--- /dev/null
+++ b/jcdm-ui/src/api/monitor/logininfor.js
@@ -0,0 +1,34 @@
+import request from '@/utils/request'
+
+// 鏌ヨ鐧诲綍鏃ュ織鍒楄〃
+export function list(query) {
+  return request({
+    url: '/monitor/logininfor/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鍒犻櫎鐧诲綍鏃ュ織
+export function delLogininfor(infoId) {
+  return request({
+    url: '/monitor/logininfor/' + infoId,
+    method: 'delete'
+  })
+}
+
+// 瑙i攣鐢ㄦ埛鐧诲綍鐘舵��
+export function unlockLogininfor(userName) {
+  return request({
+    url: '/monitor/logininfor/unlock/' + userName,
+    method: 'get'
+  })
+}
+
+// 娓呯┖鐧诲綍鏃ュ織
+export function cleanLogininfor() {
+  return request({
+    url: '/monitor/logininfor/clean',
+    method: 'delete'
+  })
+}
diff --git a/jcdm-ui/src/api/monitor/online.js b/jcdm-ui/src/api/monitor/online.js
new file mode 100644
index 0000000..bd22137
--- /dev/null
+++ b/jcdm-ui/src/api/monitor/online.js
@@ -0,0 +1,18 @@
+import request from '@/utils/request'
+
+// 鏌ヨ鍦ㄧ嚎鐢ㄦ埛鍒楄〃
+export function list(query) {
+  return request({
+    url: '/monitor/online/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 寮洪��鐢ㄦ埛
+export function forceLogout(tokenId) {
+  return request({
+    url: '/monitor/online/' + tokenId,
+    method: 'delete'
+  })
+}
diff --git a/jcdm-ui/src/api/monitor/operlog.js b/jcdm-ui/src/api/monitor/operlog.js
new file mode 100644
index 0000000..a04bca8
--- /dev/null
+++ b/jcdm-ui/src/api/monitor/operlog.js
@@ -0,0 +1,26 @@
+import request from '@/utils/request'
+
+// 鏌ヨ鎿嶄綔鏃ュ織鍒楄〃
+export function list(query) {
+  return request({
+    url: '/monitor/operlog/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鍒犻櫎鎿嶄綔鏃ュ織
+export function delOperlog(operId) {
+  return request({
+    url: '/monitor/operlog/' + operId,
+    method: 'delete'
+  })
+}
+
+// 娓呯┖鎿嶄綔鏃ュ織
+export function cleanOperlog() {
+  return request({
+    url: '/monitor/operlog/clean',
+    method: 'delete'
+  })
+}
diff --git a/jcdm-ui/src/api/monitor/server.js b/jcdm-ui/src/api/monitor/server.js
new file mode 100644
index 0000000..e1f9ca2
--- /dev/null
+++ b/jcdm-ui/src/api/monitor/server.js
@@ -0,0 +1,9 @@
+import request from '@/utils/request'
+
+// 鑾峰彇鏈嶅姟淇℃伅
+export function getServer() {
+  return request({
+    url: '/monitor/server',
+    method: 'get'
+  })
+}
\ No newline at end of file
diff --git a/jcdm-ui/src/api/system/config.js b/jcdm-ui/src/api/system/config.js
new file mode 100644
index 0000000..a404d82
--- /dev/null
+++ b/jcdm-ui/src/api/system/config.js
@@ -0,0 +1,60 @@
+import request from '@/utils/request'
+
+// 鏌ヨ鍙傛暟鍒楄〃
+export function listConfig(query) {
+  return request({
+    url: '/system/config/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ鍙傛暟璇︾粏
+export function getConfig(configId) {
+  return request({
+    url: '/system/config/' + configId,
+    method: 'get'
+  })
+}
+
+// 鏍规嵁鍙傛暟閿悕鏌ヨ鍙傛暟鍊�
+export function getConfigKey(configKey) {
+  return request({
+    url: '/system/config/configKey/' + configKey,
+    method: 'get'
+  })
+}
+
+// 鏂板鍙傛暟閰嶇疆
+export function addConfig(data) {
+  return request({
+    url: '/system/config',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼鍙傛暟閰嶇疆
+export function updateConfig(data) {
+  return request({
+    url: '/system/config',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎鍙傛暟閰嶇疆
+export function delConfig(configId) {
+  return request({
+    url: '/system/config/' + configId,
+    method: 'delete'
+  })
+}
+
+// 鍒锋柊鍙傛暟缂撳瓨
+export function refreshCache() {
+  return request({
+    url: '/system/config/refreshCache',
+    method: 'delete'
+  })
+}
diff --git a/jcdm-ui/src/api/system/dept.js b/jcdm-ui/src/api/system/dept.js
new file mode 100644
index 0000000..fc943cd
--- /dev/null
+++ b/jcdm-ui/src/api/system/dept.js
@@ -0,0 +1,52 @@
+import request from '@/utils/request'
+
+// 鏌ヨ閮ㄩ棬鍒楄〃
+export function listDept(query) {
+  return request({
+    url: '/system/dept/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ閮ㄩ棬鍒楄〃锛堟帓闄よ妭鐐癸級
+export function listDeptExcludeChild(deptId) {
+  return request({
+    url: '/system/dept/list/exclude/' + deptId,
+    method: 'get'
+  })
+}
+
+// 鏌ヨ閮ㄩ棬璇︾粏
+export function getDept(deptId) {
+  return request({
+    url: '/system/dept/' + deptId,
+    method: 'get'
+  })
+}
+
+// 鏂板閮ㄩ棬
+export function addDept(data) {
+  return request({
+    url: '/system/dept',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼閮ㄩ棬
+export function updateDept(data) {
+  return request({
+    url: '/system/dept',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎閮ㄩ棬
+export function delDept(deptId) {
+  return request({
+    url: '/system/dept/' + deptId,
+    method: 'delete'
+  })
+}
\ No newline at end of file
diff --git a/jcdm-ui/src/api/system/dict/data.js b/jcdm-ui/src/api/system/dict/data.js
new file mode 100644
index 0000000..6c9eb79
--- /dev/null
+++ b/jcdm-ui/src/api/system/dict/data.js
@@ -0,0 +1,52 @@
+import request from '@/utils/request'
+
+// 鏌ヨ瀛楀吀鏁版嵁鍒楄〃
+export function listData(query) {
+  return request({
+    url: '/system/dict/data/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ瀛楀吀鏁版嵁璇︾粏
+export function getData(dictCode) {
+  return request({
+    url: '/system/dict/data/' + dictCode,
+    method: 'get'
+  })
+}
+
+// 鏍规嵁瀛楀吀绫诲瀷鏌ヨ瀛楀吀鏁版嵁淇℃伅
+export function getDicts(dictType) {
+  return request({
+    url: '/system/dict/data/type/' + dictType,
+    method: 'get'
+  })
+}
+
+// 鏂板瀛楀吀鏁版嵁
+export function addData(data) {
+  return request({
+    url: '/system/dict/data',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼瀛楀吀鏁版嵁
+export function updateData(data) {
+  return request({
+    url: '/system/dict/data',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎瀛楀吀鏁版嵁
+export function delData(dictCode) {
+  return request({
+    url: '/system/dict/data/' + dictCode,
+    method: 'delete'
+  })
+}
diff --git a/jcdm-ui/src/api/system/dict/type.js b/jcdm-ui/src/api/system/dict/type.js
new file mode 100644
index 0000000..a7a6e01
--- /dev/null
+++ b/jcdm-ui/src/api/system/dict/type.js
@@ -0,0 +1,60 @@
+import request from '@/utils/request'
+
+// 鏌ヨ瀛楀吀绫诲瀷鍒楄〃
+export function listType(query) {
+  return request({
+    url: '/system/dict/type/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ瀛楀吀绫诲瀷璇︾粏
+export function getType(dictId) {
+  return request({
+    url: '/system/dict/type/' + dictId,
+    method: 'get'
+  })
+}
+
+// 鏂板瀛楀吀绫诲瀷
+export function addType(data) {
+  return request({
+    url: '/system/dict/type',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼瀛楀吀绫诲瀷
+export function updateType(data) {
+  return request({
+    url: '/system/dict/type',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎瀛楀吀绫诲瀷
+export function delType(dictId) {
+  return request({
+    url: '/system/dict/type/' + dictId,
+    method: 'delete'
+  })
+}
+
+// 鍒锋柊瀛楀吀缂撳瓨
+export function refreshCache() {
+  return request({
+    url: '/system/dict/type/refreshCache',
+    method: 'delete'
+  })
+}
+
+// 鑾峰彇瀛楀吀閫夋嫨妗嗗垪琛�
+export function optionselect() {
+  return request({
+    url: '/system/dict/type/optionselect',
+    method: 'get'
+  })
+}
\ No newline at end of file
diff --git a/jcdm-ui/src/api/system/menu.js b/jcdm-ui/src/api/system/menu.js
new file mode 100644
index 0000000..f6415c6
--- /dev/null
+++ b/jcdm-ui/src/api/system/menu.js
@@ -0,0 +1,60 @@
+import request from '@/utils/request'
+
+// 鏌ヨ鑿滃崟鍒楄〃
+export function listMenu(query) {
+  return request({
+    url: '/system/menu/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ鑿滃崟璇︾粏
+export function getMenu(menuId) {
+  return request({
+    url: '/system/menu/' + menuId,
+    method: 'get'
+  })
+}
+
+// 鏌ヨ鑿滃崟涓嬫媺鏍戠粨鏋�
+export function treeselect() {
+  return request({
+    url: '/system/menu/treeselect',
+    method: 'get'
+  })
+}
+
+// 鏍规嵁瑙掕壊ID鏌ヨ鑿滃崟涓嬫媺鏍戠粨鏋�
+export function roleMenuTreeselect(roleId) {
+  return request({
+    url: '/system/menu/roleMenuTreeselect/' + roleId,
+    method: 'get'
+  })
+}
+
+// 鏂板鑿滃崟
+export function addMenu(data) {
+  return request({
+    url: '/system/menu',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼鑿滃崟
+export function updateMenu(data) {
+  return request({
+    url: '/system/menu',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎鑿滃崟
+export function delMenu(menuId) {
+  return request({
+    url: '/system/menu/' + menuId,
+    method: 'delete'
+  })
+}
\ No newline at end of file
diff --git a/jcdm-ui/src/api/system/notice.js b/jcdm-ui/src/api/system/notice.js
new file mode 100644
index 0000000..c274ea5
--- /dev/null
+++ b/jcdm-ui/src/api/system/notice.js
@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 鏌ヨ鍏憡鍒楄〃
+export function listNotice(query) {
+  return request({
+    url: '/system/notice/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ鍏憡璇︾粏
+export function getNotice(noticeId) {
+  return request({
+    url: '/system/notice/' + noticeId,
+    method: 'get'
+  })
+}
+
+// 鏂板鍏憡
+export function addNotice(data) {
+  return request({
+    url: '/system/notice',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼鍏憡
+export function updateNotice(data) {
+  return request({
+    url: '/system/notice',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎鍏憡
+export function delNotice(noticeId) {
+  return request({
+    url: '/system/notice/' + noticeId,
+    method: 'delete'
+  })
+}
\ No newline at end of file
diff --git a/jcdm-ui/src/api/system/post.js b/jcdm-ui/src/api/system/post.js
new file mode 100644
index 0000000..1a8e9ca
--- /dev/null
+++ b/jcdm-ui/src/api/system/post.js
@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 鏌ヨ宀椾綅鍒楄〃
+export function listPost(query) {
+  return request({
+    url: '/system/post/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ宀椾綅璇︾粏
+export function getPost(postId) {
+  return request({
+    url: '/system/post/' + postId,
+    method: 'get'
+  })
+}
+
+// 鏂板宀椾綅
+export function addPost(data) {
+  return request({
+    url: '/system/post',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼宀椾綅
+export function updatePost(data) {
+  return request({
+    url: '/system/post',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎宀椾綅
+export function delPost(postId) {
+  return request({
+    url: '/system/post/' + postId,
+    method: 'delete'
+  })
+}
diff --git a/jcdm-ui/src/api/system/role.js b/jcdm-ui/src/api/system/role.js
new file mode 100644
index 0000000..f13e6f4
--- /dev/null
+++ b/jcdm-ui/src/api/system/role.js
@@ -0,0 +1,119 @@
+import request from '@/utils/request'
+
+// 鏌ヨ瑙掕壊鍒楄〃
+export function listRole(query) {
+  return request({
+    url: '/system/role/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ瑙掕壊璇︾粏
+export function getRole(roleId) {
+  return request({
+    url: '/system/role/' + roleId,
+    method: 'get'
+  })
+}
+
+// 鏂板瑙掕壊
+export function addRole(data) {
+  return request({
+    url: '/system/role',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼瑙掕壊
+export function updateRole(data) {
+  return request({
+    url: '/system/role',
+    method: 'put',
+    data: data
+  })
+}
+
+// 瑙掕壊鏁版嵁鏉冮檺
+export function dataScope(data) {
+  return request({
+    url: '/system/role/dataScope',
+    method: 'put',
+    data: data
+  })
+}
+
+// 瑙掕壊鐘舵�佷慨鏀�
+export function changeRoleStatus(roleId, status) {
+  const data = {
+    roleId,
+    status
+  }
+  return request({
+    url: '/system/role/changeStatus',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎瑙掕壊
+export function delRole(roleId) {
+  return request({
+    url: '/system/role/' + roleId,
+    method: 'delete'
+  })
+}
+
+// 鏌ヨ瑙掕壊宸叉巿鏉冪敤鎴峰垪琛�
+export function allocatedUserList(query) {
+  return request({
+    url: '/system/role/authUser/allocatedList',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ瑙掕壊鏈巿鏉冪敤鎴峰垪琛�
+export function unallocatedUserList(query) {
+  return request({
+    url: '/system/role/authUser/unallocatedList',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鍙栨秷鐢ㄦ埛鎺堟潈瑙掕壊
+export function authUserCancel(data) {
+  return request({
+    url: '/system/role/authUser/cancel',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鎵归噺鍙栨秷鐢ㄦ埛鎺堟潈瑙掕壊
+export function authUserCancelAll(data) {
+  return request({
+    url: '/system/role/authUser/cancelAll',
+    method: 'put',
+    params: data
+  })
+}
+
+// 鎺堟潈鐢ㄦ埛閫夋嫨
+export function authUserSelectAll(data) {
+  return request({
+    url: '/system/role/authUser/selectAll',
+    method: 'put',
+    params: data
+  })
+}
+
+// 鏍规嵁瑙掕壊ID鏌ヨ閮ㄩ棬鏍戠粨鏋�
+export function deptTreeSelect(roleId) {
+  return request({
+    url: '/system/role/deptTree/' + roleId,
+    method: 'get'
+  })
+}
diff --git a/jcdm-ui/src/api/system/user.js b/jcdm-ui/src/api/system/user.js
new file mode 100644
index 0000000..f2f76ef
--- /dev/null
+++ b/jcdm-ui/src/api/system/user.js
@@ -0,0 +1,135 @@
+import request from '@/utils/request'
+import { parseStrEmpty } from "@/utils/ruoyi";
+
+// 鏌ヨ鐢ㄦ埛鍒楄〃
+export function listUser(query) {
+  return request({
+    url: '/system/user/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ鐢ㄦ埛璇︾粏
+export function getUser(userId) {
+  return request({
+    url: '/system/user/' + parseStrEmpty(userId),
+    method: 'get'
+  })
+}
+
+// 鏂板鐢ㄦ埛
+export function addUser(data) {
+  return request({
+    url: '/system/user',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼鐢ㄦ埛
+export function updateUser(data) {
+  return request({
+    url: '/system/user',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎鐢ㄦ埛
+export function delUser(userId) {
+  return request({
+    url: '/system/user/' + userId,
+    method: 'delete'
+  })
+}
+
+// 鐢ㄦ埛瀵嗙爜閲嶇疆
+export function resetUserPwd(userId, password) {
+  const data = {
+    userId,
+    password
+  }
+  return request({
+    url: '/system/user/resetPwd',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鐢ㄦ埛鐘舵�佷慨鏀�
+export function changeUserStatus(userId, status) {
+  const data = {
+    userId,
+    status
+  }
+  return request({
+    url: '/system/user/changeStatus',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鏌ヨ鐢ㄦ埛涓汉淇℃伅
+export function getUserProfile() {
+  return request({
+    url: '/system/user/profile',
+    method: 'get'
+  })
+}
+
+// 淇敼鐢ㄦ埛涓汉淇℃伅
+export function updateUserProfile(data) {
+  return request({
+    url: '/system/user/profile',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鐢ㄦ埛瀵嗙爜閲嶇疆
+export function updateUserPwd(oldPassword, newPassword) {
+  const data = {
+    oldPassword,
+    newPassword
+  }
+  return request({
+    url: '/system/user/profile/updatePwd',
+    method: 'put',
+    params: data
+  })
+}
+
+// 鐢ㄦ埛澶村儚涓婁紶
+export function uploadAvatar(data) {
+  return request({
+    url: '/system/user/profile/avatar',
+    method: 'post',
+    data: data
+  })
+}
+
+// 鏌ヨ鎺堟潈瑙掕壊
+export function getAuthRole(userId) {
+  return request({
+    url: '/system/user/authRole/' + userId,
+    method: 'get'
+  })
+}
+
+// 淇濆瓨鎺堟潈瑙掕壊
+export function updateAuthRole(data) {
+  return request({
+    url: '/system/user/authRole',
+    method: 'put',
+    params: data
+  })
+}
+
+// 鏌ヨ閮ㄩ棬涓嬫媺鏍戠粨鏋�
+export function deptTreeSelect() {
+  return request({
+    url: '/system/user/deptTree',
+    method: 'get'
+  })
+}
diff --git a/jcdm-ui/src/api/tool/gen.js b/jcdm-ui/src/api/tool/gen.js
new file mode 100644
index 0000000..4506927
--- /dev/null
+++ b/jcdm-ui/src/api/tool/gen.js
@@ -0,0 +1,76 @@
+import request from '@/utils/request'
+
+// 鏌ヨ鐢熸垚琛ㄦ暟鎹�
+export function listTable(query) {
+  return request({
+    url: '/tool/gen/list',
+    method: 'get',
+    params: query
+  })
+}
+// 鏌ヨdb鏁版嵁搴撳垪琛�
+export function listDbTable(query) {
+  return request({
+    url: '/tool/gen/db/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ琛ㄨ缁嗕俊鎭�
+export function getGenTable(tableId) {
+  return request({
+    url: '/tool/gen/' + tableId,
+    method: 'get'
+  })
+}
+
+// 淇敼浠g爜鐢熸垚淇℃伅
+export function updateGenTable(data) {
+  return request({
+    url: '/tool/gen',
+    method: 'put',
+    data: data
+  })
+}
+
+// 瀵煎叆琛�
+export function importTable(data) {
+  return request({
+    url: '/tool/gen/importTable',
+    method: 'post',
+    params: data
+  })
+}
+
+// 棰勮鐢熸垚浠g爜
+export function previewTable(tableId) {
+  return request({
+    url: '/tool/gen/preview/' + tableId,
+    method: 'get'
+  })
+}
+
+// 鍒犻櫎琛ㄦ暟鎹�
+export function delTable(tableId) {
+  return request({
+    url: '/tool/gen/' + tableId,
+    method: 'delete'
+  })
+}
+
+// 鐢熸垚浠g爜锛堣嚜瀹氫箟璺緞锛�
+export function genCode(tableName) {
+  return request({
+    url: '/tool/gen/genCode/' + tableName,
+    method: 'get'
+  })
+}
+
+// 鍚屾鏁版嵁搴�
+export function synchDb(tableName) {
+  return request({
+    url: '/tool/gen/synchDb/' + tableName,
+    method: 'get'
+  })
+}
diff --git a/jcdm-ui/src/assets/401_images/401.gif b/jcdm-ui/src/assets/401_images/401.gif
new file mode 100644
index 0000000..cd6e0d9
--- /dev/null
+++ b/jcdm-ui/src/assets/401_images/401.gif
Binary files differ
diff --git a/jcdm-ui/src/assets/404_images/404.png b/jcdm-ui/src/assets/404_images/404.png
new file mode 100644
index 0000000..3d8e230
--- /dev/null
+++ b/jcdm-ui/src/assets/404_images/404.png
Binary files differ
diff --git a/jcdm-ui/src/assets/404_images/404_cloud.png b/jcdm-ui/src/assets/404_images/404_cloud.png
new file mode 100644
index 0000000..c6281d0
--- /dev/null
+++ b/jcdm-ui/src/assets/404_images/404_cloud.png
Binary files differ
diff --git a/jcdm-ui/src/assets/icons/index.js b/jcdm-ui/src/assets/icons/index.js
new file mode 100644
index 0000000..2c6b309
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/index.js
@@ -0,0 +1,9 @@
+import Vue from 'vue'
+import SvgIcon from '@/components/SvgIcon'// svg component
+
+// register globally
+Vue.component('svg-icon', SvgIcon)
+
+const req = require.context('./svg', false, /\.svg$/)
+const requireAll = requireContext => requireContext.keys().map(requireContext)
+requireAll(req)
diff --git a/jcdm-ui/src/assets/icons/svg/404.svg b/jcdm-ui/src/assets/icons/svg/404.svg
new file mode 100644
index 0000000..6df5019
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/404.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M121.718 73.272v9.953c3.957-7.584 6.199-16.05 6.199-24.995C127.917 26.079 99.273 0 63.958 0 28.644 0 0 26.079 0 58.23c0 .403.028.806.028 1.21l22.97-25.953h13.34l-19.76 27.187h6.42V53.77l13.728-19.477v49.361H22.998V73.272H2.158c5.951 20.284 23.608 36.208 45.998 41.399-1.44 3.3-5.618 11.263-12.565 12.674-8.607 1.764 23.358.428 46.163-13.178 17.519-4.611 31.938-15.849 39.77-30.513h-13.506V73.272H85.02V59.464l22.998-25.977h13.008l-19.429 27.187h6.421v-7.433l13.727-19.402v39.433h-.027zm-78.24 2.822a10.516 10.516 0 0 1-.996-4.535V44.548c0-1.613.332-3.124.996-4.535a11.66 11.66 0 0 1 2.713-3.68c1.134-1.032 2.49-1.864 4.04-2.468 1.55-.605 3.21-.908 4.982-.908h11.292c1.77 0 3.431.303 4.981.908 1.522.604 2.85 1.41 3.986 2.418l-12.26 16.303v-2.898a1.96 1.96 0 0 0-.665-1.512c-.443-.403-.996-.604-1.66-.604-.665 0-1.218.201-1.661.604a1.96 1.96 0 0 0-.664 1.512v9.071L44.364 77.606a10.556 10.556 0 0 1-.886-1.512zm35.73-4.535c0 1.613-.332 3.124-.997 4.535a11.66 11.66 0 0 1-2.712 3.68c-1.134 1.032-2.49 1.864-4.04 2.469-1.55.604-3.21.907-4.982.907H55.185c-1.77 0-3.431-.303-4.981-.907-1.55-.605-2.906-1.437-4.041-2.47a12.49 12.49 0 0 1-1.384-1.512l13.727-18.217v6.375c0 .605.222 1.109.665 1.512.442.403.996.604 1.66.604.664 0 1.218-.201 1.66-.604a1.96 1.96 0 0 0 .665-1.512V53.87L75.97 36.838c.913.932 1.66 1.99 2.214 3.175.664 1.41.996 2.922.996 4.535v27.011h.028z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/bug.svg b/jcdm-ui/src/assets/icons/svg/bug.svg
new file mode 100644
index 0000000..05a150d
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/bug.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M127.88 73.143c0 1.412-.506 2.635-1.518 3.669-1.011 1.033-2.209 1.55-3.592 1.55h-17.887c0 9.296-1.783 17.178-5.35 23.645l16.609 17.044c1.011 1.034 1.517 2.257 1.517 3.67 0 1.412-.506 2.635-1.517 3.668-.958 1.033-2.155 1.55-3.593 1.55-1.438 0-2.635-.517-3.593-1.55l-15.811-16.063a15.49 15.49 0 0 1-1.196 1.06c-.532.434-1.65 1.208-3.353 2.322a50.104 50.104 0 0 1-5.192 2.974c-1.758.87-3.94 1.658-6.546 2.364-2.607.706-5.189 1.06-7.748 1.06V47.044H58.89v73.062c-2.716 0-5.417-.367-8.106-1.102-2.688-.734-5.003-1.631-6.945-2.692a66.769 66.769 0 0 1-5.268-3.179c-1.571-1.057-2.73-1.94-3.476-2.65L33.9 109.34l-14.611 16.877c-1.066 1.14-2.344 1.711-3.833 1.711-1.277 0-2.422-.434-3.434-1.304-1.012-.978-1.557-2.187-1.635-3.627-.079-1.44.333-2.705 1.236-3.794l16.129-18.51c-3.087-6.197-4.63-13.644-4.63-22.342H5.235c-1.383 0-2.58-.517-3.592-1.55S.125 74.545.125 73.132c0-1.412.506-2.635 1.518-3.668 1.012-1.034 2.21-1.55 3.592-1.55h17.887V43.939L9.308 29.833c-1.012-1.033-1.517-2.256-1.517-3.669 0-1.412.505-2.635 1.517-3.668 1.012-1.034 2.21-1.55 3.593-1.55s2.58.516 3.593 1.55l13.813 14.106h67.396l13.814-14.106c1.012-1.034 2.21-1.55 3.592-1.55 1.384 0 2.581.516 3.593 1.55 1.012 1.033 1.518 2.256 1.518 3.668 0 1.413-.506 2.636-1.518 3.67l-13.814 14.105v23.975h17.887c1.383 0 2.58.516 3.593 1.55 1.011 1.033 1.517 2.256 1.517 3.668l-.005.01zM89.552 26.175H38.448c0-7.23 2.489-13.386 7.466-18.469C50.892 2.623 56.92.082 64 .082c7.08 0 13.108 2.541 18.086 7.624 4.977 5.083 7.466 11.24 7.466 18.469z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/build.svg b/jcdm-ui/src/assets/icons/svg/build.svg
new file mode 100644
index 0000000..97c4688
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/build.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1568899741379" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2054" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M960 591.424V368.96c0-0.288 0.16-0.512 0.16-0.768S960 367.68 960 367.424V192a32 32 0 0 0-32-32H96a32 32 0 0 0-32 32v175.424c0 0.288-0.16 0.512-0.16 0.768s0.16 0.48 0.16 0.768v222.464c0 0.288-0.16 0.512-0.16 0.768s0.16 0.48 0.16 0.768V864a32 32 0 0 0 32 32h832a32 32 0 0 0 32-32v-271.04c0-0.288 0.16-0.512 0.16-0.768S960 591.68 960 591.424z m-560-31.232v-160H608v160h-208z m208 64V832h-208v-207.808H608z m-480-224h208v160H128v-160z m544 0h224v160h-224v-160zM896 224v112.192H128V224h768zM128 624.192h208V832H128v-207.808zM672 832v-207.808h224V832h-224z" p-id="2055"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/button.svg b/jcdm-ui/src/assets/icons/svg/button.svg
new file mode 100644
index 0000000..904fddc
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/button.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1588670460195" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1314" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M230.4 307.712c13.824 0 25.088-11.264 25.088-25.088 0-100.352 81.92-182.272 182.272-182.272s182.272 81.408 182.272 182.272c0 13.824 11.264 25.088 25.088 25.088s25.088-11.264 24.576-25.088c0-127.488-103.936-231.936-231.936-231.936S205.824 154.624 205.824 282.624c-0.512 14.336 10.752 25.088 24.576 25.088z m564.736 234.496c-11.264 0-21.504 2.048-31.232 6.144 0-44.544-40.448-81.92-88.064-81.92-14.848 0-28.16 3.584-39.936 10.24-13.824-28.16-44.544-48.128-78.848-48.128-12.288 0-24.576 2.56-35.328 7.68V284.16c0-45.568-37.888-81.92-84.48-81.92s-84.48 36.864-84.48 81.92v348.672l-69.12-112.64c-18.432-28.16-58.368-36.864-91.136-19.968-26.624 14.336-46.592 47.104-30.208 88.064 3.072 8.192 76.8 205.312 171.52 311.296 0 0 28.16 24.576 43.008 58.88 4.096 9.728 13.312 15.36 22.528 15.36 3.072 0 6.656-0.512 9.728-2.048 12.288-5.12 18.432-19.968 12.8-32.256-19.456-44.544-53.76-74.752-53.76-74.752C281.6 768 209.408 573.44 208.384 570.88c-5.12-12.8-2.56-20.992 7.168-26.112 9.216-4.608 21.504-4.608 26.112 2.56l113.152 184.32c4.096 8.704 12.8 14.336 22.528 14.336 13.824 0 25.088-10.752 25.088-25.088V284.16c0-17.92 15.36-32.256 34.816-32.256s34.816 14.336 34.816 32.256v284.16c0 13.824 10.24 25.088 24.576 25.088 13.824 0 25.088-11.264 25.088-25.088v-57.344c0-17.92 15.36-32.768 34.816-32.768 19.968 0 37.376 15.36 37.376 32.768v95.232c0 7.168 3.072 13.312 7.68 17.92 4.608 4.608 10.752 7.168 17.92 7.168 13.824 0 24.576-11.264 24.576-25.088V547.84c0-18.432 13.824-32.256 32.256-32.256 20.48 0 38.912 15.36 38.912 32.256v95.232c0 13.824 11.264 25.088 25.088 25.088s24.576-11.264 25.088-25.088v-18.944c0-18.944 12.8-32.256 30.72-32.256 18.432 0 22.528 18.944 22.528 31.744 0 1.024-11.776 99.84-50.688 173.056-30.72 58.368-45.056 112.128-51.2 146.944-2.56 13.312 6.656 26.112 19.968 28.672 1.536 0 3.072 0.512 4.608 0.512 11.776 0 22.016-8.192 24.064-20.48 5.632-31.232 18.432-79.36 46.08-132.608 43.52-81.92 55.808-186.88 56.32-193.536-0.512-50.688-29.696-83.968-72.704-83.968z"></path></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/cascader.svg b/jcdm-ui/src/assets/icons/svg/cascader.svg
new file mode 100644
index 0000000..e256024
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/cascader.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1576153230908" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="971" xmlns:xlink="http://www.w3.org/1999/xlink" width="81" height="81"><defs><style type="text/css"></style></defs><path d="M772.87036133 734.06115723c-43.34106445 0-80.00793458 27.93273926-93.76831055 66.57714843H475.90991211c-56.60705567 0-102.66723633-46.06018067-102.66723633-102.66723633V600.82446289h305.859375c13.76037598 38.64440918 50.42724609 66.57714844 93.76831055 66.57714844 55.12390137 0 99.94812012-44.82421875 99.94812012-99.94812012S827.9942627 467.50537109 772.87036133 467.50537109c-43.34106445 0-80.00793458 27.93273926-93.76831055 66.57714844H373.24267578V401.01062011h321.92687989c55.12390137 0 99.94812012-44.82421875 99.94812011-99.94812011V190.07312011C795.11767578 134.94921875 750.29345703 90.125 695.16955567 90.125H251.12963867C196.0057373 90.125 151.18151855 134.94921875 151.18151855 190.07312011V301.0625c0 55.12390137 44.82421875 99.94812012 99.94812012 99.94812012h55.53588867v296.96044921c0 93.35632325 75.97045898 169.32678223 169.32678224 169.32678223h203.19213866c13.76037598 38.64440918 50.42724609 66.57714844 93.76831055 66.57714844 55.12390137 0 99.94812012-44.82421875 99.94812012-99.94812012s-44.90661622-99.86572266-100.03051758-99.86572265z m0-199.89624024c18.37463379 0 33.28857422 14.91394043 33.28857422 33.28857423s-14.91394043 33.28857422-33.28857422 33.28857421-33.28857422-14.91394043-33.28857422-33.28857421 14.91394043-33.28857422 33.28857422-33.28857422zM217.75866699 301.0625V190.07312011c0-18.37463379 14.91394043-33.28857422 33.28857423-33.28857421h444.03991698c18.37463379 0 33.28857422 14.91394043 33.28857422 33.28857422V301.0625c0 18.37463379-14.91394043 33.28857422-33.28857422 33.28857422H251.12963867c-18.37463379 0-33.37097168-14.91394043-33.37097168-33.28857422z m555.11169434 566.23535156c-18.37463379 0-33.28857422-14.91394043-33.28857422-33.28857422 0-18.37463379 14.91394043-33.28857422 33.28857422-33.28857422s33.28857422 14.91394043 33.28857422 33.28857422c0.08239747 18.29223633-14.91394043 33.28857422-33.28857422 33.28857422z" p-id="972"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/chart.svg b/jcdm-ui/src/assets/icons/svg/chart.svg
new file mode 100644
index 0000000..27728fb
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/chart.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M0 54.857h36.571V128H0V54.857zM91.429 27.43H128V128H91.429V27.429zM45.714 0h36.572v128H45.714V0z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/checkbox.svg b/jcdm-ui/src/assets/icons/svg/checkbox.svg
new file mode 100644
index 0000000..013fd3a
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/checkbox.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1575982282951" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="902" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M828.40625 90.125H195.59375C137.375 90.125 90.125 137.375 90.125 195.59375v632.8125c0 58.21875 47.25 105.46875 105.46875 105.46875h632.8125c58.21875 0 105.46875-47.25 105.46875-105.46875V195.59375c0-58.21875-47.25-105.46875-105.46875-105.46875z m52.734375 738.28125c0 29.16-23.57015625 52.734375-52.734375 52.734375H195.59375c-29.109375 0-52.734375-23.574375-52.734375-52.734375V195.59375c0-29.109375 23.625-52.734375 52.734375-52.734375h632.8125c29.16 0 52.734375 23.625 52.734375 52.734375v632.8125z" p-id="903"></path><path d="M421.52890625 709.55984375a36.28125 36.28125 0 0 1-27.55265625-12.66890625L205.17453125 476.613125a36.28546875 36.28546875 0 0 1 55.10109375-47.22890625l164.986875 192.4846875 342.16171875-298.48078125a36.2896875 36.2896875 0 0 1 47.70984375 54.68765625L445.3859375 700.6203125a36.3234375 36.3234375 0 0 1-23.85703125 8.93953125z" p-id="904"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/clipboard.svg b/jcdm-ui/src/assets/icons/svg/clipboard.svg
new file mode 100644
index 0000000..90923ff
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/clipboard.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M54.857 118.857h64V73.143H89.143c-1.902 0-3.52-.668-4.855-2.002-1.335-1.335-2.002-2.954-2.002-4.855V36.57H54.857v82.286zM73.143 16v-4.571a2.2 2.2 0 0 0-.677-1.61 2.198 2.198 0 0 0-1.609-.676H20.571c-.621 0-1.158.225-1.609.676a2.198 2.198 0 0 0-.676 1.61V16a2.2 2.2 0 0 0 .676 1.61c.451.45.988.676 1.61.676h50.285c.622 0 1.158-.226 1.61-.677.45-.45.676-.987.676-1.609zm18.286 48h21.357L91.43 42.642V64zM128 73.143v48c0 1.902-.667 3.52-2.002 4.855-1.335 1.335-2.953 2.002-4.855 2.002H52.57c-1.901 0-3.52-.667-4.854-2.002-1.335-1.335-2.003-2.953-2.003-4.855v-11.429H6.857c-1.902 0-3.52-.667-4.855-2.002C.667 106.377 0 104.759 0 102.857v-96c0-1.902.667-3.52 2.002-4.855C3.337.667 4.955 0 6.857 0h77.714c1.902 0 3.52.667 4.855 2.002 1.335 1.335 2.003 2.953 2.003 4.855V30.29c1 .622 1.856 1.29 2.569 2.003l29.147 29.147c1.335 1.335 2.478 3.145 3.429 5.43.95 2.287 1.426 4.383 1.426 6.291v-.018z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/code.svg b/jcdm-ui/src/assets/icons/svg/code.svg
new file mode 100644
index 0000000..5f9c5ab
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/code.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1546567861908" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2422" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M318.577778 819.2L17.066667 512l301.511111-307.2 45.511111 45.511111L96.711111 512l267.377778 261.688889zM705.422222 819.2l-45.511111-45.511111L927.288889 512l-267.377778-261.688889 45.511111-45.511111L1006.933333 512zM540.785778 221.866667l55.751111 11.150222L483.157333 802.133333l-55.751111-11.093333z" p-id="2423"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/color.svg b/jcdm-ui/src/assets/icons/svg/color.svg
new file mode 100644
index 0000000..44a81aa
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/color.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1577252187056" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2508" xmlns:xlink="http://www.w3.org/1999/xlink" width="81" height="81"><defs><style type="text/css"></style></defs><path d="M747.59340925 691.12859384c11.51396329 0.25305413 22.43746719-0.21087818 40.74171707-1.51832482 29.35428085-2.10878421 35.84933734-2.36183835 46.47761114-0.8856895 24.71495444 3.37405491 41.12129828 21.76265671 32.47528161 47.95376084-85.57447632 258.19957947-442.00123984 249.76444099-628.67084683 50.73735554-153.47733892-159.33976008-153.09775772-414.41833795 0.92786545-573.42069196 159.71934128-162.67163983 424.03439521-166.59397897 565.78689185 0.63263534 80.38686649 94.81095318 108.34934958 169.16669549 89.11723508 230.57450162-15.01454608 47.99593598-50.61082928 77.68762207-119.77896259 114.63352789-4.89237973 2.65706845-29.35428085 15.52065436-35.84933652 19.02123633-46.94154346 25.30541465-63.51659033 41.20565021-62.20914449 58.45550757 2.95229856 39.13904114 24.16667102 52.7196135 70.98168823 53.81618115z m44.41100207 50.10472101c-19.82257471 1.43397372-32.05352527 1.940082-45.63409763 1.6448519-70.34905207-1.60267593-115.98314969-30.91478165-121.38163769-101.64341492-3.45840683-46.05585397 24.7571304-73.13264758 89.24376132-107.96976837 6.7902866-3.66928501 31.37871396-16.57504688 36.06021551-19.06341229 57.69634516-30.83042972 85.15271997-53.73183005 94.76877722-84.47790866 12.77923398-40.78389304-9.10994898-98.94417051-79.24812286-181.6507002-121.17075953-142.97559219-350.14258521-139.60153647-489.2380134 2.06660824-134.49827774 138.84237405-134.79350784 362.12048163-0.42175717 501.637667 158.53842169 168.99799328 451.9968783 181.18676788 534.57688175-11.80919339-4.68150156 0.2952301-10.71262573 0.67481131-18.72600705 1.26527069z" p-id="2509"></path><path d="M346.03865637 637.18588562a78.82636652 78.82636652 0 0 0 78.32025825-79.29029883c0-43.69401562-35.005823-79.29029883-78.32025825-79.29029882a78.82636652 78.82636652 0 0 0-78.36243338 79.29029882c0 43.69401562 35.005823 79.29029883 78.36243338 79.29029883z m0-51.7495729a27.07679361 27.07679361 0 0 1-26.5706845-27.54072593c0-15.30977536 11.97789643-27.54072593 26.5706845-27.54072592 14.55061295 0 26.57068533 12.23095057 26.57068533 27.54072592a27.07679361 27.07679361 0 0 1-26.57068533 27.54072593zM475.7289063 807.11174353a78.82636652 78.82636652 0 0 0 78.3624334-79.29029882c0-43.69401562-34.96364785-79.29029883-78.32025825-79.29029883a78.82636652 78.82636652 0 0 0-78.32025742 79.29029883c0 43.69401562 34.96364785 79.29029883 78.32025742 79.29029882z m0-51.74957208a27.07679361 27.07679361 0 0 1-26.57068532-27.54072674c0-15.30977536 12.06224753-27.54072593 26.57068532-27.54072593 14.59278892 0 26.57068533 12.23095057 26.57068453 27.54072593a27.07679361 27.07679361 0 0 1-26.57068453 27.54072674zM601.24376214 377.21492718a78.82636652 78.82636652 0 0 0 78.32025742-79.29029883c0-43.69401562-34.96364785-79.29029883-78.32025742-79.29029882a78.82636652 78.82636652 0 0 0-78.32025823 79.29029883c0 43.69401562 34.96364785 79.29029883 78.32025824 79.29029883z m1e-8-51.74957208a27.07679361 27.07679361 0 0 1-26.57068534-27.54072675c0-15.30977536 11.97789643-27.54072593 26.57068534-27.54072591 14.55061295 0 26.57068533 12.23095057 26.57068451 27.54072592a27.07679361 27.07679361 0 0 1-26.57068451 27.54072674zM378.80916809 433.85687983a78.82636652 78.82636652 0 0 0 78.32025824-79.29029883c0-43.69401562-34.96364785-79.29029883-78.32025824-79.29029802a78.82636652 78.82636652 0 0 0-78.32025742 79.29029802c0 43.69401562 34.96364785 79.29029883 78.32025742 79.29029883z m0-51.74957209a27.07679361 27.07679361 0 0 1-26.57068451-27.54072674c0-15.30977536 11.97789643-27.54072593 26.57068451-27.54072593 14.55061295 0 26.57068533 12.23095057 26.57068533 27.54072593a27.07679361 27.07679361 0 0 1-26.57068533 27.54072674z" p-id="2510"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/component.svg b/jcdm-ui/src/assets/icons/svg/component.svg
new file mode 100644
index 0000000..29c3458
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/component.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1575804206892" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3145" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M826.56 470.016c-32.896 0-64.384 12.288-89.984 35.52l0-104.96c0-62.208-50.496-112.832-112.64-113.088L623.936 287.04 519.552 287.104C541.824 262.72 554.56 230.72 554.56 197.12c0-73.536-59.904-133.44-133.504-133.44-73.472 0-133.376 59.904-133.376 133.44 0 32.896 12.224 64.256 35.52 89.984L175.232 287.104l0 0.576C113.728 288.704 64 338.88 64 400.576l0.32 0 0.32 116.48C60.864 544.896 70.592 577.728 100.8 588.48c12.736 4.608 37.632 7.488 60.864-25.28 12.992-18.368 34.24-29.248 56.64-29.248 38.336 0 69.504 31.104 69.504 69.312 0 38.4-31.168 69.504-69.504 69.504-22.656 0-44.032-11.264-57.344-30.4C138.688 610.112 112.576 615.36 102.464 619.136c-29.824 10.752-39.104 43.776-38.144 67.392l0 160.384L64 846.912C64 909.248 114.752 960 177.216 960l446.272 0c62.4 0 113.152-50.752 113.152-113.152l0-145.024c24.384 22.272 56.384 35.008 89.984 35.008 73.536 0 133.44-59.904 133.44-133.504C960 529.92 900.096 470.016 826.56 470.016zM826.56 672.896c-22.72 0-44.032-11.264-57.344-30.4-22.272-32.384-48.448-27.136-58.56-23.36-29.824 10.752-39.04 43.776-38.08 67.392l0 160.384c0 27.136-22.016 49.152-49.152 49.152L177.216 896.064C150.08 896 128 873.984 128 846.848l0.32 0 0-145.024c24.384 22.272 56.384 35.008 89.984 35.008 73.6 0 133.504-59.904 133.504-133.504 0-73.472-59.904-133.376-133.504-133.376-32.896 0-64.32 12.288-89.984 35.52l0-104.96L128 400.512c0-27.072 22.08-49.152 49.216-49.152L177.216 351.04 334.656 350.72c3.776 0.512 7.616 0.832 11.52 0.832 24.896 0 50.752-10.816 60.032-37.056 4.544-12.736 7.424-37.568-25.344-60.736C362.624 240.768 351.68 219.52 351.68 197.12c0-38.272 31.104-69.44 69.376-69.44 38.336 0 69.504 31.168 69.504 69.44 0 22.72-11.264 44.032-30.528 57.472C427.968 276.736 433.088 302.784 436.8 313.024c10.752 29.888 43.072 39.232 67.392 38.08l119.232 0 0 0.384c27.136 0 49.152 22.08 49.152 49.152l0.256 116.48c-3.776 27.84 6.016 60.736 36.224 71.488 12.736 4.608 37.632 7.488 60.8-25.28 13.056-18.368 34.24-29.248 56.704-29.248C864.832 534.016 896 565.12 896 603.392 896 641.728 864.832 672.896 826.56 672.896z" p-id="3146"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/dashboard.svg b/jcdm-ui/src/assets/icons/svg/dashboard.svg
new file mode 100644
index 0000000..5317d37
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/dashboard.svg
@@ -0,0 +1 @@
+<svg width="128" height="100" xmlns="http://www.w3.org/2000/svg"><path d="M27.429 63.638c0-2.508-.893-4.65-2.679-6.424-1.786-1.775-3.94-2.662-6.464-2.662-2.524 0-4.679.887-6.465 2.662-1.785 1.774-2.678 3.916-2.678 6.424 0 2.508.893 4.65 2.678 6.424 1.786 1.775 3.94 2.662 6.465 2.662 2.524 0 4.678-.887 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zm13.714-31.801c0-2.508-.893-4.65-2.679-6.424-1.785-1.775-3.94-2.662-6.464-2.662-2.524 0-4.679.887-6.464 2.662-1.786 1.774-2.679 3.916-2.679 6.424 0 2.508.893 4.65 2.679 6.424 1.785 1.774 3.94 2.662 6.464 2.662 2.524 0 4.679-.888 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zM71.714 65.98l7.215-27.116c.285-1.23.107-2.378-.536-3.443-.643-1.064-1.56-1.762-2.75-2.094-1.19-.33-2.333-.177-3.429.462-1.095.639-1.81 1.573-2.143 2.804l-7.214 27.116c-2.857.237-5.405 1.266-7.643 3.088-2.238 1.822-3.738 4.152-4.5 6.992-.952 3.644-.476 7.098 1.429 10.364 1.905 3.265 4.69 5.37 8.357 6.317 3.667.947 7.143.474 10.429-1.42 3.285-1.892 5.404-4.66 6.357-8.305.762-2.84.619-5.607-.429-8.305-1.047-2.697-2.762-4.85-5.143-6.46zm47.143-2.342c0-2.508-.893-4.65-2.678-6.424-1.786-1.775-3.94-2.662-6.465-2.662-2.524 0-4.678.887-6.464 2.662-1.786 1.774-2.679 3.916-2.679 6.424 0 2.508.893 4.65 2.679 6.424 1.786 1.775 3.94 2.662 6.464 2.662 2.524 0 4.679-.887 6.465-2.662 1.785-1.775 2.678-3.916 2.678-6.424zm-45.714-45.43c0-2.509-.893-4.65-2.679-6.425C68.68 10.01 66.524 9.122 64 9.122c-2.524 0-4.679.887-6.464 2.661-1.786 1.775-2.679 3.916-2.679 6.425 0 2.508.893 4.65 2.679 6.424 1.785 1.774 3.94 2.662 6.464 2.662 2.524 0 4.679-.888 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zm32 13.629c0-2.508-.893-4.65-2.679-6.424-1.785-1.775-3.94-2.662-6.464-2.662-2.524 0-4.679.887-6.464 2.662-1.786 1.774-2.679 3.916-2.679 6.424 0 2.508.893 4.65 2.679 6.424 1.785 1.774 3.94 2.662 6.464 2.662 2.524 0 4.679-.888 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zM128 63.638c0 12.351-3.357 23.78-10.071 34.286-.905 1.372-2.19 2.058-3.858 2.058H13.93c-1.667 0-2.953-.686-3.858-2.058C3.357 87.465 0 76.037 0 63.638c0-8.613 1.69-16.847 5.071-24.703C8.452 31.08 13 24.312 18.714 18.634c5.715-5.68 12.524-10.199 20.429-13.559C47.048 1.715 55.333.035 64 .035c8.667 0 16.952 1.68 24.857 5.04 7.905 3.36 14.714 7.88 20.429 13.559 5.714 5.678 10.262 12.446 13.643 20.301 3.38 7.856 5.071 16.09 5.071 24.703z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/date-range.svg b/jcdm-ui/src/assets/icons/svg/date-range.svg
new file mode 100644
index 0000000..fda571e
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/date-range.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1579774833889" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1376" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M887.466667 192.853333h-100.693334V119.466667c0-10.24-6.826667-17.066667-17.066666-17.066667s-17.066667 6.826667-17.066667 17.066667v73.386666H303.786667V119.466667c0-10.24-6.826667-17.066667-17.066667-17.066667s-17.066667 6.826667-17.066667 17.066667v73.386666H168.96c-46.08 0-85.333333 37.546667-85.333333 85.333334V836.266667c0 46.08 37.546667 85.333333 85.333333 85.333333H887.466667c46.08 0 85.333333-37.546667 85.333333-85.333333V278.186667c0-47.786667-37.546667-85.333333-85.333333-85.333334z m-718.506667 34.133334h100.693333v66.56c0 10.24 6.826667 17.066667 17.066667 17.066666s17.066667-6.826667 17.066667-17.066666v-66.56h450.56v66.56c0 10.24 6.826667 17.066667 17.066666 17.066666s17.066667-6.826667 17.066667-17.066666v-66.56H887.466667c27.306667 0 51.2 22.186667 51.2 51.2v88.746666H117.76v-88.746666c0-29.013333 22.186667-51.2 51.2-51.2zM887.466667 887.466667H168.96c-27.306667 0-51.2-22.186667-51.2-51.2V401.066667H938.666667V836.266667c0 27.306667-22.186667 51.2-51.2 51.2z" p-id="1377"></path><path d="M858.453333 493.226667H327.68c-10.24 0-17.066667 6.826667-17.066667 17.066666v114.346667h-116.053333c-10.24 0-17.066667 6.826667-17.066667 17.066667v133.12c0 10.24 6.826667 17.066667 17.066667 17.066666H460.8c10.24 0 17.066667-6.826667 17.066667-17.066666v-114.346667h380.586666c10.24 0 17.066667-6.826667 17.066667-17.066667v-133.12c0-10.24-6.826667-17.066667-17.066667-17.066666z m-413.013333 34.133333v97.28h-98.986667v-97.28h98.986667z m-230.4 131.413333h98.986667v98.986667h-98.986667v-98.986667z m131.413333 97.28v-97.28h98.986667v97.28h-98.986667z m133.12-228.693333h97.28v98.986667h-97.28v-98.986667z m131.413334 0h98.986666v98.986667h-98.986666v-98.986667z m230.4 97.28h-98.986667v-98.986667h98.986667v98.986667z" p-id="1378"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/date.svg b/jcdm-ui/src/assets/icons/svg/date.svg
new file mode 100644
index 0000000..52dc73e
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/date.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1577186573535" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1068" xmlns:xlink="http://www.w3.org/1999/xlink" width="81" height="81"><defs><style type="text/css"></style></defs><path d="M479.85714249 608.42857168h64.28571502c19.28571417 0 32.14285751-12.85714249 32.14285664-32.14285751s-12.85714249-32.14285751-32.14285664-32.14285664h-64.28571504c-19.28571417 0-32.14285751 12.85714249-32.14285664 32.14285662s12.85714249 32.14285751 32.14285664 32.14285753z m-2e-8 122.14285665h64.28571504c19.28571417 0 32.14285751-12.85714249 32.14285664-32.14285665s-12.85714249-32.14285751-32.14285664-32.14285751h-64.28571504c-19.28571417 0-32.14285751 12.85714249-32.14285664 32.14285751s12.85714249 32.14285751 32.14285664 32.14285664z m353.57142921-559.28571416h-128.57142921v-32.14285664c0-19.28571417-12.85714249-32.14285751-32.14285664-32.14285753s-32.14285751 12.85714249-32.14285751 32.14285753v32.14285664h-257.14285665v-32.14285664c0-19.28571417-12.85714249-32.14285751-32.14285752-32.14285753s-32.14285751 12.85714249-32.14285664 32.14285753v32.14285664h-128.57142919c-70.71428585 0-128.57142832 57.85714249-128.57142832 122.14285751v501.42857081c0 70.71428585 57.85714249 128.57142832 128.57142832 122.14285751h642.85714335c70.71428585 0 128.57142832-57.85714249 128.57142833-122.14285751v-501.42857081c0-70.71428585-57.85714249-122.14285753-128.57142833-122.14285751z m64.28571415 623.57142832c0 32.14285751-32.14285751 64.28571415-64.28571416 64.28571504h-642.85714335c-32.14285751 0-64.28571415-25.71428583-64.28571417-64.28571504v-372.85714249h771.42857168v372.85714249z m0-437.14285664h-771.42857168v-64.28571417c0-32.14285751 32.14285751-64.28571415 64.28571417-64.28571415h128.57142919v32.14285664c0 19.28571417 12.85714249 32.14285751 32.14285664 32.14285751s32.14285751-12.85714249 32.14285753-32.14285751v-32.14285664h257.14285665v32.14285664c0 19.28571417 12.85714249 32.14285751 32.1428575 32.14285751s32.14285751-12.85714249 32.14285664-32.14285751v-32.14285664h128.57142921c32.14285751 0 64.28571415 25.71428583 64.28571415 64.28571415v64.28571417z m-610.71428583 372.85714247h64.28571415c19.28571417 0 32.14285751-12.85714249 32.14285753-32.14285664s-12.85714249-32.14285751-32.14285753-32.14285751h-64.28571415c-19.28571417 0-32.14285751 12.85714249-32.14285751 32.14285751s12.85714249 32.14285751 32.14285751 32.14285665z m385.71428583-122.14285664h64.28571417c19.28571417 0 32.14285751-12.85714249 32.14285751-32.14285751s-12.85714249-32.14285751-32.14285751-32.14285664h-64.28571415c-19.28571417 0-32.14285751 12.85714249-32.14285753 32.14285664s12.85714249 32.14285751 32.14285753 32.14285751z m-385.71428583 0h64.28571415c19.28571417 0 32.14285751-12.85714249 32.14285753-32.14285751s-12.85714249-32.14285751-32.14285753-32.14285664h-64.28571415c-19.28571417 0-32.14285751 12.85714249-32.14285751 32.14285664s12.85714249 32.14285751 32.14285751 32.14285751z m385.71428583 122.14285665h64.28571417c19.28571417 0 32.14285751-12.85714249 32.14285751-32.14285665s-12.85714249-32.14285751-32.14285751-32.14285751h-64.28571415c-19.28571417 0-32.14285751 12.85714249-32.14285753 32.14285751s12.85714249 32.14285751 32.14285753 32.14285665z" p-id="1069"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/dict.svg b/jcdm-ui/src/assets/icons/svg/dict.svg
new file mode 100644
index 0000000..4849377
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/dict.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1566035680909" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3601" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M1002.0848 744.672l-33.568 10.368c0.96 7.264 2.144 14.304 2.144 21.76 0 7.328-1.184 14.432-2.368 21.568l33.792 10.56c7.936 2.24 14.496 7.616 18.336 14.752 3.84 7.328 4.672 15.808 1.952 23.552-5.376 16-23.168 24.672-39.936 19.68l-34.176-10.624c-7.136 12.8-15.776 24.672-26.208 35.2l20.8 27.488a28.96 28.96 0 0 1 5.824 22.816 29.696 29.696 0 0 1-12.704 19.616 32.544 32.544 0 0 1-44.416-6.752l-20.8-27.552c-13.696 6.56-28.192 11.2-43.008 13.888v33.632c0 16.736-14.112 30.432-31.648 30.432-17.6 0-31.872-13.696-31.872-30.432v-33.632a167.616 167.616 0 0 1-42.88-13.888l-20.928 27.552c-10.72 13.76-30.08 16.64-44.288 6.752a29.632 29.632 0 0 1-12.704-19.616 29.28 29.28 0 0 1 5.696-22.816l20.896-27.808a166.72 166.72 0 0 1-27.008-34.688l-33.376 10.432c-16.8 5.184-34.56-3.552-39.936-19.616a29.824 29.824 0 0 1 20.224-38.24l33.472-10.432c-0.8-7.264-2.016-14.304-2.016-21.824 0-7.36 1.184-14.496 2.304-21.632l-33.792-10.368c-16.672-5.376-25.632-22.496-20.224-38.432 5.376-16 23.136-24.672 39.936-19.68l34.016 10.752c7.328-12.672 15.84-24.8 26.336-35.328l-20.8-27.552a29.44 29.44 0 0 1 6.944-42.432 32.704 32.704 0 0 1 44.384 6.752l20.832 27.616c13.696-6.432 28.224-11.2 43.104-13.952v-33.568c0-16.736 14.048-30.432 31.648-30.432 17.536 0 31.808 13.568 31.808 30.432v33.504c15.072 2.688 29.344 7.808 42.848 14.016l20.992-27.616a32.48 32.48 0 0 1 44.224-6.752 29.568 29.568 0 0 1 7.136 42.432l-21.024 27.808c10.432 10.432 19.872 21.888 27.04 34.752l33.376-10.432c16.768-5.12 34.56 3.68 39.936 19.68 5.536 15.936-3.712 33.056-20.32 38.304z m-206.016-74.432c-61.344 0-111.136 47.808-111.136 106.56 0 58.88 49.792 106.496 111.136 106.496 61.312 0 111.104-47.616 111.104-106.496 0-58.752-49.792-106.56-111.104-106.56z" p-id="3602"></path><path d="M802.7888 57.152h-76.448c0-22.08-21.024-38.24-42.848-38.24H39.3968a39.68 39.68 0 0 0-39.36 40.032v795.616s41.888 120.192 110.752 120.192H673.2848a227.488 227.488 0 0 1-107.04-97.44H117.6368s-40.608-13.696-40.608-41.248l470.304-0.256 1.664 3.36a227.68 227.68 0 0 1-12.64-73.632c0-60.576 24-118.624 66.88-161.44a228.352 228.352 0 0 1 123.552-63.392l-3.2 0.288 2.144-424.672h38.208l0.576 421.024c27.04 0 52.672 4.8 76.64 13.344V101.536c0.032 0-6.304-44.384-38.368-44.384zM149.7648 514.336H72.3888v-77.408H149.7648v77.408z m0-144.32H72.3888v-77.44H149.7648v77.44z m0-137.248H72.3888v-77.44H149.7648v77.44z m501.856 281.568H206.0848v-77.408h445.536v77.408z m0-144.32H206.0848v-77.44h445.536v77.44z m0-137.248H206.0848v-77.44h445.536v77.44z" p-id="3603"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/documentation.svg b/jcdm-ui/src/assets/icons/svg/documentation.svg
new file mode 100644
index 0000000..7043122
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/documentation.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M71.984 44.815H115.9L71.984 9.642v35.173zM16.094.05h63.875l47.906 38.37v76.74c0 3.392-1.682 6.645-4.677 9.044-2.995 2.399-7.056 3.746-11.292 3.746H16.094c-4.236 0-8.297-1.347-11.292-3.746-2.995-2.399-4.677-5.652-4.677-9.044V12.84C.125 5.742 7.23.05 16.094.05zm71.86 102.32V89.58h-71.86v12.79h71.86zm23.952-25.58V64H16.094v12.79h95.812z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/download.svg b/jcdm-ui/src/assets/icons/svg/download.svg
new file mode 100644
index 0000000..c896951
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/download.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1569915748289" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3062" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M768.35456 416a256 256 0 1 0-512 0 192 192 0 1 0 0 384v64a256 256 0 0 1-58.88-505.216 320.128 320.128 0 0 1 629.76 0A256.128 256.128 0 0 1 768.35456 864v-64a192 192 0 0 0 0-384z m-512 384h64v64H256.35456v-64z m448 0h64v64h-64v-64z" fill="#333333" p-id="3063"></path><path d="M539.04256 845.248V512.192a32.448 32.448 0 0 0-32-32.192c-17.664 0-32 14.912-32 32.192v333.056l-36.096-36.096a32.192 32.192 0 0 0-45.056 0.192 31.616 31.616 0 0 0-0.192 45.056l90.88 90.944a31.36 31.36 0 0 0 22.528 9.088 30.08 30.08 0 0 0 22.4-9.088l90.88-90.88a32.192 32.192 0 0 0-0.192-45.12 31.616 31.616 0 0 0-45.056-0.192l-36.096 36.096z" fill="#333333" p-id="3064"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/drag.svg b/jcdm-ui/src/assets/icons/svg/drag.svg
new file mode 100644
index 0000000..4185d3c
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/drag.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M73.137 29.08h-9.209 29.7L63.886.093 34.373 29.08h20.49v27.035H27.238v17.948h27.625v27.133h18.274V74.063h27.41V56.115h-27.41V29.08zm-9.245 98.827l27.518-26.711H36.59l27.302 26.71zM.042 64.982l27.196 27.029V38.167L.042 64.982zm100.505-26.815V92.01l27.41-27.029-27.41-26.815z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/druid.svg b/jcdm-ui/src/assets/icons/svg/druid.svg
new file mode 100644
index 0000000..a2b4b4e
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/druid.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1566036347051" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5853" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M832 128H192a64.19 64.19 0 0 0-64 64v640a64.19 64.19 0 0 0 64 64h640a64.19 64.19 0 0 0 64-64V192a64.19 64.19 0 0 0-64-64z m0 703.89l-0.11 0.11H192.11l-0.11-0.11V768h640zM832 544H720L605.6 696.54 442.18 435.07 333.25 544H192v-64h114.75l147.07-147.07L610.4 583.46 688 480h144z m0-288H192v-63.89l0.11-0.11h639.78l0.11 0.11z" p-id="5854"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/edit.svg b/jcdm-ui/src/assets/icons/svg/edit.svg
new file mode 100644
index 0000000..d26101f
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/edit.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M106.133 67.2a4.797 4.797 0 0 0-4.8 4.8c0 .187.014.36.027.533h-.027V118.4H9.6V26.667h50.133c2.654 0 4.8-2.147 4.8-4.8 0-2.654-2.146-4.8-4.8-4.8H9.6a9.594 9.594 0 0 0-9.6 9.6V118.4c0 5.307 4.293 9.6 9.6 9.6h91.733c5.307 0 9.6-4.293 9.6-9.6V72.533h-.026c.013-.173.026-.346.026-.533 0-2.653-2.146-4.8-4.8-4.8z"/><path d="M125.16 13.373L114.587 2.8c-3.747-3.747-9.854-3.72-13.6.027l-52.96 52.96a4.264 4.264 0 0 0-.907 1.36L33.813 88.533c-.746 1.76-.226 3.534.907 4.68 1.133 1.147 2.92 1.667 4.693.92l31.4-13.293c.507-.213.96-.52 1.36-.907l52.96-52.96c3.747-3.746 3.774-9.853.027-13.6zM66.107 72.4l-18.32 7.76 7.76-18.32L92.72 24.667l10.56 10.56L66.107 72.4zm52.226-52.227l-8.266 8.267-10.56-10.56 8.266-8.267.027-.026 10.56 10.56-.027.026z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/education.svg b/jcdm-ui/src/assets/icons/svg/education.svg
new file mode 100644
index 0000000..7bfb01d
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/education.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M88.883 119.565c-7.284 0-19.434 2.495-21.333 8.25v.127c-4.232.13-5.222 0-7.108 0-1.895-5.76-14.045-8.256-21.333-8.256H0V0h42.523c9.179 0 17.109 5.47 21.47 13.551C68.352 5.475 76.295 0 85.478 0H128v119.57l-39.113-.005h-.004zM60.442 24.763c0-9.651-8.978-16.507-17.777-16.507H7.108V111.43H39.11c7.054-.14 18.177.082 21.333 6.12v-4.628c-.134-5.722-.004-13.522 0-13.832V27.413l.004-2.655-.004.005zm60.442-16.517h-35.55c-8.802 0-17.78 6.856-17.78 16.493v74.259c.004.32.138 8.115 0 13.813v4.627c3.155-6.022 14.279-6.26 21.333-6.114h32V8.25l-.003-.005z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/email.svg b/jcdm-ui/src/assets/icons/svg/email.svg
new file mode 100644
index 0000000..74d25e2
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/email.svg
@@ -0,0 +1 @@
+<svg width="128" height="96" xmlns="http://www.w3.org/2000/svg"><path d="M64.125 56.975L120.188.912A12.476 12.476 0 0 0 115.5 0h-103c-1.588 0-3.113.3-4.513.838l56.138 56.137z"/><path d="M64.125 68.287l-62.3-62.3A12.42 12.42 0 0 0 0 12.5v71C0 90.4 5.6 96 12.5 96h103c6.9 0 12.5-5.6 12.5-12.5v-71a12.47 12.47 0 0 0-1.737-6.35L64.125 68.287z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/example.svg b/jcdm-ui/src/assets/icons/svg/example.svg
new file mode 100644
index 0000000..46f42b5
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/example.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M96.258 57.462h31.421C124.794 27.323 100.426 2.956 70.287.07v31.422a32.856 32.856 0 0 1 25.971 25.97zm-38.796-25.97V.07C27.323 2.956 2.956 27.323.07 57.462h31.422a32.856 32.856 0 0 1 25.97-25.97zm12.825 64.766v31.421c30.46-2.885 54.507-27.253 57.713-57.712H96.579c-2.886 13.466-13.146 23.726-26.292 26.291zM31.492 70.287H.07c2.886 30.46 27.253 54.507 57.713 57.713V96.579c-13.466-2.886-23.726-13.146-26.291-26.292z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/excel.svg b/jcdm-ui/src/assets/icons/svg/excel.svg
new file mode 100644
index 0000000..74d97b8
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/excel.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M78.208 16.576v8.384h38.72v5.376h-38.72v8.704h38.72v5.376h-38.72v8.576h38.72v5.376h-38.72v8.576h38.72v5.376h-38.72v8.576h38.72v5.376h-38.72v8.512h38.72v5.376h-38.72v11.136H128v-94.72H78.208zM0 114.368L72.128 128V0L0 13.632v100.736z"/><path d="M28.672 82.56h-11.2l14.784-23.488-14.08-22.592h11.52l8.192 14.976 8.448-14.976h11.136l-14.08 22.208L58.368 82.56H46.656l-8.768-15.68z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/exit-fullscreen.svg b/jcdm-ui/src/assets/icons/svg/exit-fullscreen.svg
new file mode 100644
index 0000000..485c128
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/exit-fullscreen.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M49.217 41.329l-.136-35.24c-.06-2.715-2.302-4.345-5.022-4.405h-3.65c-2.712-.06-4.866 2.303-4.806 5.016l.152 19.164-24.151-23.79a6.698 6.698 0 0 0-9.499 0 6.76 6.76 0 0 0 0 9.526l23.93 23.713-18.345.074c-2.712-.069-5.228 1.813-5.64 5.02v3.462c.069 2.721 2.31 4.97 5.022 5.03l35.028-.207c.052.005.087.025.133.025l2.457.054a4.626 4.626 0 0 0 3.436-1.38c.88-.874 1.205-2.096 1.169-3.462l-.262-2.465c0-.048.182-.081.182-.136h.002zm52.523 51.212l18.32-.073c2.713.06 5.224-1.609 5.64-4.815v-3.462c-.068-2.722-2.317-4.97-5.021-5.04l-34.58.21c-.053 0-.086-.021-.138-.021l-2.451-.06a4.64 4.64 0 0 0-3.445 1.381c-.885.868-1.201 2.094-1.174 3.46l.27 2.46c.005.06-.177.095-.177.141l.141 34.697c.069 2.713 2.31 4.338 5.022 4.397l3.45.006c2.705.062 4.867-2.31 4.8-5.026l-.153-18.752 24.151 23.946a6.69 6.69 0 0 0 9.494 0 6.747 6.747 0 0 0 0-9.523L101.74 92.54v.001zM48.125 80.662a4.636 4.636 0 0 0-3.437-1.382l-2.457.06c-.05 0-.082.022-.137.022l-35.025-.21c-2.712.07-4.957 2.318-5.022 5.04v3.462c.409 3.206 2.925 4.874 5.633 4.814l18.554.06-24.132 23.928c-2.62 2.626-2.62 6.89 0 9.524a6.694 6.694 0 0 0 9.496 0l24.155-23.79-.155 18.866c-.06 2.722 2.094 5.093 4.801 5.025h3.65c2.72-.069 4.962-1.685 5.022-4.406l.141-34.956c0-.05-.182-.082-.182-.136l.262-2.46c.03-1.366-.286-2.592-1.166-3.46h-.001zM80.08 47.397a4.62 4.62 0 0 0 3.443 1.374l2.45-.054c.055 0 .088-.02.143-.028l35.08.21c2.712-.062 4.953-2.312 5.021-5.033l.009-3.463c-.417-3.211-2.937-5.084-5.64-5.025l-18.615-.073 23.917-23.715c2.63-2.623 2.63-6.879.008-9.513a6.691 6.691 0 0 0-9.494 0L92.251 26.016l.155-19.312c.065-2.713-2.097-5.085-4.802-5.025h-3.45c-2.713.069-4.954 1.693-5.022 4.406l-.139 35.247c0 .054.18.088.18.136l-.267 2.465c-.028 1.366.288 2.588 1.174 3.463v.001z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/eye-open.svg b/jcdm-ui/src/assets/icons/svg/eye-open.svg
new file mode 100644
index 0000000..88dcc98
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/eye-open.svg
@@ -0,0 +1 @@
+<svg class="icon" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="128" height="128"><defs><style/></defs><path d="M512 128q69.675 0 135.51 21.163t115.498 54.997 93.483 74.837 73.685 82.006 51.67 74.837 32.17 54.827L1024 512q-2.347 4.992-6.315 13.483T998.87 560.17t-31.658 51.669-44.331 59.99-56.832 64.34-69.504 60.16-82.347 51.5-94.848 34.687T512 896q-69.675 0-135.51-21.163t-115.498-54.826-93.483-74.326-73.685-81.493-51.67-74.496-32.17-54.997L0 513.707q2.347-4.992 6.315-13.483t18.816-34.816 31.658-51.84 44.331-60.33 56.832-64.683 69.504-60.331 82.347-51.84 94.848-34.816T512 128.085zm0 85.333q-46.677 0-91.648 12.331t-81.152 31.83-70.656 47.146-59.648 54.485-48.853 57.686-37.675 52.821-26.325 43.99q12.33 21.674 26.325 43.52t37.675 52.351 48.853 57.003 59.648 53.845T339.2 767.02t81.152 31.488T512 810.667t91.648-12.331 81.152-31.659 70.656-46.848 59.648-54.186 48.853-57.344 37.675-52.651T927.957 512q-12.33-21.675-26.325-43.648t-37.675-52.65-48.853-57.345-59.648-54.186-70.656-46.848-81.152-31.659T512 213.334zm0 128q70.656 0 120.661 50.006T682.667 512 632.66 632.661 512 682.667 391.339 632.66 341.333 512t50.006-120.661T512 341.333zm0 85.334q-35.328 0-60.33 25.002T426.666 512t25.002 60.33T512 597.334t60.33-25.002T597.334 512t-25.002-60.33T512 426.666z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/eye.svg b/jcdm-ui/src/assets/icons/svg/eye.svg
new file mode 100644
index 0000000..16ed2d8
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/eye.svg
@@ -0,0 +1 @@
+<svg width="128" height="64" xmlns="http://www.w3.org/2000/svg"><path d="M127.072 7.994c1.37-2.208.914-5.152-.914-6.87-2.056-1.717-4.797-1.226-6.396.982-.229.245-25.586 32.382-55.74 32.382-29.24 0-55.74-32.382-55.968-32.627-1.6-1.963-4.57-2.208-6.397-.49C-.17 3.086-.399 6.275 1.2 8.238c.457.736 5.94 7.36 14.62 14.72L4.17 35.96c-1.828 1.963-1.6 5.152.228 6.87.457.98 1.6 1.471 2.742 1.471s2.284-.49 3.198-1.472l12.564-13.983c5.94 4.416 13.021 8.587 20.788 11.53l-4.797 17.418c-.685 2.699.686 5.397 3.198 6.133h1.37c2.057 0 3.884-1.472 4.341-3.68L52.6 42.83c3.655.736 7.538 1.227 11.422 1.227 3.883 0 7.767-.49 11.422-1.227l4.797 17.173c.457 2.208 2.513 3.68 4.34 3.68.457 0 .914 0 1.143-.246 2.513-.736 3.883-3.434 3.198-6.133l-4.797-17.172c7.767-2.944 14.848-7.114 20.788-11.53l12.336 13.738c.913.981 2.056 1.472 3.198 1.472s2.284-.49 3.198-1.472c1.828-1.963 1.828-4.906.228-6.87l-11.65-13.001c9.366-7.36 14.849-14.474 14.849-14.474z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/form.svg b/jcdm-ui/src/assets/icons/svg/form.svg
new file mode 100644
index 0000000..dcbaa18
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/form.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M84.068 23.784c-1.02 0-1.877-.32-2.572-.96a8.588 8.588 0 0 1-1.738-2.237 11.524 11.524 0 0 1-1.042-2.621c-.232-.895-.348-1.641-.348-2.238V0h.278c.834 0 1.622.085 2.363.256.742.17 1.645.575 2.711 1.214 1.066.64 2.363 1.535 3.892 2.686 1.53 1.15 3.453 2.664 5.77 4.54 2.502 2.045 4.494 3.771 5.977 5.178 1.483 1.406 2.618 2.6 3.406 3.58.787.98 1.274 1.812 1.46 2.494.185.682.277 1.278.277 1.79v2.046H84.068zM127.3 84.01c.278.682.464 1.535.556 2.558.093 1.023-.37 2.003-1.39 2.94-.463.427-.88.832-1.25 1.215-.372.384-.696.704-.974.96a6.69 6.69 0 0 1-.973.767l-11.816-10.741a44.331 44.331 0 0 0 1.877-1.535 31.028 31.028 0 0 1 1.737-1.406c1.112-.938 2.317-1.343 3.615-1.215 1.297.128 2.363.405 3.197.83.927.427 1.923 1.173 2.989 2.239 1.065 1.065 1.876 2.195 2.432 3.388zM78.23 95.902c2.038 0 3.752-.511 5.143-1.534l-26.969 25.83H18.037c-1.761 0-3.684-.47-5.77-1.407a24.549 24.549 0 0 1-5.838-3.709 21.373 21.373 0 0 1-4.518-5.306c-1.204-2.003-1.807-4.07-1.807-6.202V16.495c0-1.79.44-3.665 1.32-5.626A18.41 18.41 0 0 1 5.04 5.562a21.798 21.798 0 0 1 5.213-3.964C12.198.533 14.237 0 16.37 0h53.24v15.984c0 1.62.278 3.367.834 5.242a16.704 16.704 0 0 0 2.572 5.179c1.159 1.577 2.665 2.898 4.518 3.964 1.853 1.066 4.078 1.598 6.673 1.598h20.295v42.325L85.458 92.45c1.02-1.364 1.529-2.856 1.529-4.476 0-2.216-.857-4.113-2.572-5.69-1.714-1.577-3.776-2.366-6.186-2.366H26.1c-2.409 0-4.448.789-6.116 2.366-1.668 1.577-2.502 3.474-2.502 5.69 0 2.217.834 4.092 2.502 5.626 1.668 1.535 3.707 2.302 6.117 2.302h52.13zM26.1 47.951c-2.41 0-4.449.789-6.117 2.366-1.668 1.577-2.502 3.473-2.502 5.69 0 2.216.834 4.092 2.502 5.626 1.668 1.534 3.707 2.302 6.117 2.302h52.13c2.409 0 4.47-.768 6.185-2.302 1.715-1.534 2.572-3.41 2.572-5.626 0-2.217-.857-4.113-2.572-5.69-1.714-1.577-3.776-2.366-6.186-2.366H26.1zm52.407 64.063l1.807-1.663 3.476-3.196a479.75 479.75 0 0 0 4.587-4.284 500.757 500.757 0 0 1 5.004-4.667c3.985-3.666 8.48-7.758 13.485-12.276l11.677 10.741-13.485 12.404-5.004 4.603-4.587 4.22a179.46 179.46 0 0 0-3.267 3.068c-.88.853-1.367 1.322-1.46 1.407-.463.341-.973.703-1.529 1.087-.556.383-1.112.703-1.668.959-.556.256-1.413.575-2.572.959a83.5 83.5 0 0 1-3.545 1.087 72.2 72.2 0 0 1-3.475.895c-1.112.256-1.946.426-2.502.511-1.112.17-1.854.043-2.224-.383-.371-.426-.464-1.151-.278-2.174.092-.511.278-1.279.556-2.302.278-1.023.602-2.067.973-3.132l1.042-3.005c.325-.938.58-1.577.765-1.918a10.157 10.157 0 0 1 2.224-2.941z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/fullscreen.svg b/jcdm-ui/src/assets/icons/svg/fullscreen.svg
new file mode 100644
index 0000000..0e86b6f
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/fullscreen.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M38.47 52L52 38.462l-23.648-23.67L43.209 0H.035L0 43.137l14.757-14.865L38.47 52zm74.773 47.726L89.526 76 76 89.536l23.648 23.672L84.795 128h43.174L128 84.863l-14.757 14.863zM89.538 52l23.668-23.648L128 43.207V.038L84.866 0 99.73 14.76 76 38.472 89.538 52zM38.46 76L14.792 99.651 0 84.794v43.173l43.137.033-14.865-14.757L52 89.53 38.46 76z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/github.svg b/jcdm-ui/src/assets/icons/svg/github.svg
new file mode 100644
index 0000000..db0a0d4
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/github.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1581238998885" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4187" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M511.542857 14.057143C228.914286 13.942857 0 242.742857 0 525.142857 0 748.457143 143.2 938.285714 342.628571 1008c26.857143 6.742857 22.742857-12.342857 22.742858-25.371429v-88.571428c-155.085714 18.171429-161.371429-84.457143-171.771429-101.6C172.571429 756.571429 122.857143 747.428571 137.714286 730.285714c35.314286-18.171429 71.314286 4.571429 113.028571 66.171429 30.171429 44.685714 89.028571 37.142857 118.857143 29.714286 6.514286-26.857143 20.457143-50.857143 39.657143-69.485715-160.685714-28.8-227.657143-126.857143-227.657143-243.428571 0-56.571429 18.628571-108.571429 55.2-150.514286-23.314286-69.142857 2.171429-128.342857 5.6-137.142857 66.4-5.942857 135.428571 47.542857 140.8 51.771429 37.714286-10.171429 80.8-15.542857 129.028571-15.542858 48.457143 0 91.657143 5.6 129.714286 15.885715 12.914286-9.828571 76.914286-55.771429 138.628572-50.171429 3.314286 8.8 28.228571 66.628571 6.285714 134.857143 37.028571 42.057143 55.885714 94.514286 55.885714 151.2 0 116.8-67.428571 214.971429-228.571428 243.314286a145.714286 145.714286 0 0 1 43.542857 104v128.571428c0.914286 10.285714 0 20.457143 17.142857 20.457143 202.4-68.228571 348.114286-259.428571 348.114286-484.685714 0-282.514286-229.028571-511.2-511.428572-511.2z" p-id="4188"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/guide.svg b/jcdm-ui/src/assets/icons/svg/guide.svg
new file mode 100644
index 0000000..b271001
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/guide.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M1.482 70.131l36.204 16.18 69.932-65.485-61.38 70.594 46.435 18.735c1.119.425 2.397-.17 2.797-1.363v-.085L127.998.047 1.322 65.874c-1.12.597-1.519 1.959-1.04 3.151.32.511.72.937 1.2 1.107zm44.676 57.821L64.22 107.26l-18.062-7.834v28.527z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/icon.svg b/jcdm-ui/src/assets/icons/svg/icon.svg
new file mode 100644
index 0000000..82be8ee
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/icon.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M115.147.062a13 13 0 0 1 4.94.945c1.55.63 2.907 1.526 4.069 2.688a13.148 13.148 0 0 1 2.761 4.069c.678 1.55 1.017 3.245 1.017 5.086v102.3c0 3.681-1.187 6.733-3.56 9.155-2.373 2.422-5.352 3.633-8.937 3.633H12.992c-3.875 0-7-1.26-9.373-3.779-2.373-2.518-3.56-5.667-3.56-9.445V12.704c0-3.39 1.163-6.345 3.488-8.863C5.872 1.32 8.972.062 12.847.062h102.3zM81.434 109.047c1.744 0 3.003-.412 3.778-1.235.775-.824 1.163-1.914 1.163-3.27 0-1.26-.388-2.325-1.163-3.197-.775-.872-2.034-1.307-3.778-1.307H72.57c.097-.194.145-.485.145-.872V27.09h9.01c1.743 0 2.954-.436 3.633-1.308.678-.872 1.017-1.938 1.017-3.197 0-1.26-.34-2.325-1.017-3.197-.679-.872-1.89-1.308-3.633-1.308H46.268c-1.743 0-2.954.436-3.632 1.308-.678.872-1.018 1.938-1.018 3.197 0 1.26.34 2.325 1.018 3.197.678.872 1.889 1.308 3.632 1.308h8.138v72.075c0 .193.024.339.073.436.048.096.072.242.072.436H46.56c-1.744 0-3.003.435-3.778 1.307-.775.872-1.163 1.938-1.163 3.197 0 1.356.388 2.446 1.163 3.27.775.823 2.034 1.235 3.778 1.235h34.875z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/input.svg b/jcdm-ui/src/assets/icons/svg/input.svg
new file mode 100644
index 0000000..ab91381
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/input.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1575802859706" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3102" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M896 224H128c-35.2 0-64 28.8-64 64v448c0 35.2 28.8 64 64 64h768c35.2 0 64-28.8 64-64V288c0-35.2-28.8-64-64-64z m0 480c0 19.2-12.8 32-32 32H160c-19.2 0-32-12.8-32-32V320c0-19.2 12.8-32 32-32h704c19.2 0 32 12.8 32 32v384z" p-id="3103"></path><path d="M224 352c-19.2 0-32 12.8-32 32v256c0 16 12.8 32 32 32s32-12.8 32-32V384c0-16-12.8-32-32-32z" p-id="3104"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/international.svg b/jcdm-ui/src/assets/icons/svg/international.svg
new file mode 100644
index 0000000..e9b56ee
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/international.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M83.287 103.01c-1.57-3.84-6.778-10.414-15.447-19.548-2.327-2.444-2.182-4.306-1.338-9.862v-.64c.553-3.81 1.513-6.05 14.313-8.087 6.516-1.018 8.203 1.57 10.589 5.178l.785 1.193a12.625 12.625 0 0 0 6.43 5.207c1.134.524 2.53 1.164 4.421 2.24 4.596 2.53 4.596 5.41 4.596 11.753v.727a26.91 26.91 0 0 1-5.178 17.454 59.055 59.055 0 0 1-19.025 11.026c3.49-6.546.814-14.313 0-16.553l-.146-.087zM64 5.12a58.502 58.502 0 0 1 25.484 5.818 54.313 54.313 0 0 0-12.859 10.327c-.93 1.28-1.716 2.473-2.472 3.579-2.444 3.694-3.637 5.352-5.818 5.614a25.105 25.105 0 0 1-4.219 0c-4.276-.29-10.094-.64-11.956 4.422-1.193 3.23-1.396 11.956 2.444 16.495.66 1.077.778 2.4.32 3.578a7.01 7.01 0 0 1-2.066 3.229 18.938 18.938 0 0 1-2.909-2.91 18.91 18.91 0 0 0-8.32-6.603c-1.25-.349-2.647-.64-3.985-.93-3.782-.786-8.03-1.688-9.019-3.812a14.895 14.895 0 0 1-.727-5.818 21.935 21.935 0 0 0-1.396-9.25 8.873 8.873 0 0 0-5.557-4.946A58.705 58.705 0 0 1 64 5.12zM0 64c0 35.346 28.654 64 64 64 35.346 0 64-28.654 64-64 0-35.346-28.654-64-64-64C28.654 0 0 28.654 0 64z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/job.svg b/jcdm-ui/src/assets/icons/svg/job.svg
new file mode 100644
index 0000000..2a93a25
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/job.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1566036191400" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5472" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M934.912 1016.832H192c-14.336 0-25.6-11.264-25.6-25.6v-189.44c0-14.336 11.264-25.6 25.6-25.6s25.6 11.264 25.6 25.6v163.84h691.712V64H217.6v148.48c0 14.336-11.264 25.6-25.6 25.6s-25.6-11.264-25.6-25.6v-174.08c0-14.336 11.264-25.6 25.6-25.6h742.912c14.336 0 25.6 11.264 25.6 25.6v952.832c0 14.336-11.264 25.6-25.6 25.6z" p-id="5473"></path><path d="M232.96 371.2h-117.76c-14.336 0-25.6-11.264-25.6-25.6s11.264-25.6 25.6-25.6h117.76c14.336 0 25.6 11.264 25.6 25.6s-11.264 25.6-25.6 25.6zM232.96 540.16h-117.76c-14.336 0-25.6-11.264-25.6-25.6s11.264-25.6 25.6-25.6h117.76c14.336 0 25.6 11.264 25.6 25.6s-11.264 25.6-25.6 25.6zM232.96 698.88h-117.76c-14.336 0-25.6-11.264-25.6-25.6s11.264-25.6 25.6-25.6h117.76c14.336 0 25.6 11.264 25.6 25.6s-11.264 25.6-25.6 25.6zM574.464 762.88c-134.144 0-243.2-109.056-243.2-243.2S440.32 276.48 574.464 276.48s243.2 109.056 243.2 243.2-109.056 243.2-243.2 243.2z m0-435.2c-105.984 0-192 86.016-192 192S468.48 711.68 574.464 711.68s192-86.016 192-192S680.448 327.68 574.464 327.68z" p-id="5474"></path><path d="M663.04 545.28h-87.04c-14.336 0-25.6-11.264-25.6-25.6s11.264-25.6 25.6-25.6h87.04c14.336 0 25.6 11.264 25.6 25.6s-11.264 25.6-25.6 25.6z" p-id="5475"></path><path d="M576 545.28c-14.336 0-25.6-11.264-25.6-25.6v-87.04c0-14.336 11.264-25.6 25.6-25.6s25.6 11.264 25.6 25.6v87.04c0 14.336-11.264 25.6-25.6 25.6z" p-id="5476"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/language.svg b/jcdm-ui/src/assets/icons/svg/language.svg
new file mode 100644
index 0000000..0082b57
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/language.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M84.742 36.8c2.398 7.2 5.595 12.8 11.19 18.4 4.795-4.8 7.992-11.2 10.39-18.4h-21.58zm-52.748 40h20.78l-10.39-28-10.39 28z"/><path d="M111.916 0H16.009C7.218 0 .025 7.2.025 16v96c0 8.8 7.193 16 15.984 16h95.907c8.791 0 15.984-7.2 15.984-16V16c0-8.8-6.394-16-15.984-16zM72.754 103.2c-1.598 1.6-3.197 1.6-4.795 1.6-.8 0-2.398 0-3.197-.8-.8-.8-1.599 0-1.599-.8s-.799-1.6-1.598-3.2c-.8-1.6-.8-2.4-1.599-4l-3.196-8.8H28.797L25.6 96c-1.598 3.2-2.398 5.6-3.197 7.2-.8 1.6-2.398 1.6-4.795 1.6-1.599 0-3.197-.8-4.796-1.6-1.598-1.6-2.397-2.4-2.397-4 0-.8 0-1.6.799-3.2.8-1.6.8-2.4 1.598-4l17.583-44.8c.8-1.6.8-3.2 1.599-4.8.799-1.6 1.598-3.2 2.397-4 .8-.8 1.599-2.4 3.197-3.2 1.599-.8 3.197-.8 4.796-.8 1.598 0 3.196 0 4.795.8 1.598.8 2.398 1.6 3.197 3.2.799.8 1.598 2.4 2.397 4 .8 1.6 1.599 3.2 2.398 5.6l17.583 44c1.598 3.2 2.398 5.6 2.398 7.2-.8.8-1.599 2.4-2.398 4zM116.711 72c-8.791-3.2-15.185-7.2-20.78-12-5.594 5.6-12.787 9.6-21.579 12l-2.397-4c8.791-2.4 15.984-5.6 21.579-11.2C87.939 51.2 83.144 44 81.545 36h-7.992v-3.2h21.58c-1.6-2.4-3.198-5.6-4.796-8l2.397-.8c1.599 2.4 3.997 5.6 5.595 8.8h19.98v4h-7.992c-2.397 8-6.393 15.2-11.189 20 5.595 4.8 11.988 8.8 20.78 11.2l-3.197 4z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/link.svg b/jcdm-ui/src/assets/icons/svg/link.svg
new file mode 100644
index 0000000..48197ba
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/link.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M115.625 127.937H.063V12.375h57.781v12.374H12.438v90.813h90.813V70.156h12.374z"/><path d="M116.426 2.821l8.753 8.753-56.734 56.734-8.753-8.745z"/><path d="M127.893 37.982h-12.375V12.375H88.706V0h39.187z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/list.svg b/jcdm-ui/src/assets/icons/svg/list.svg
new file mode 100644
index 0000000..20259ed
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/list.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M1.585 12.087c0 6.616 3.974 11.98 8.877 11.98 4.902 0 8.877-5.364 8.877-11.98 0-6.616-3.975-11.98-8.877-11.98-4.903 0-8.877 5.364-8.877 11.98zM125.86.107H35.613c-1.268 0-2.114 1.426-2.114 2.852v18.255c0 1.712 1.057 2.853 2.114 2.853h90.247c1.268 0 2.114-1.426 2.114-2.853V2.96c0-1.711-1.057-2.852-2.114-2.852zM.106 62.86c0 6.615 3.974 11.979 8.876 11.979 4.903 0 8.877-5.364 8.877-11.98 0-6.616-3.974-11.98-8.877-11.98-4.902 0-8.876 5.364-8.876 11.98zM124.17 50.88H33.921c-1.268 0-2.114 1.425-2.114 2.851v18.256c0 1.711 1.057 2.852 2.114 2.852h90.247c1.268 0 2.114-1.426 2.114-2.852V53.73c0-1.426-.846-2.852-2.114-2.852zM.106 115.913c0 6.616 3.974 11.98 8.876 11.98 4.903 0 8.877-5.364 8.877-11.98 0-6.616-3.974-11.98-8.877-11.98-4.902 0-8.876 5.364-8.876 11.98zm124.064-11.98H33.921c-1.268 0-2.114 1.426-2.114 2.853v18.255c0 1.711 1.057 2.852 2.114 2.852h90.247c1.268 0 2.114-1.426 2.114-2.852v-18.255c0-1.427-.846-2.853-2.114-2.853z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/lock.svg b/jcdm-ui/src/assets/icons/svg/lock.svg
new file mode 100644
index 0000000..74fee54
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/lock.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M119.88 49.674h-7.987V39.52C111.893 17.738 90.45.08 63.996.08 37.543.08 16.1 17.738 16.1 39.52v10.154H8.113c-4.408 0-7.987 2.94-7.987 6.577v65.13c0 3.637 3.57 6.577 7.987 6.577H119.88c4.407 0 7.987-2.94 7.987-6.577v-65.13c-.008-3.636-3.58-6.577-7.987-6.577zm-23.953 0H32.065V39.52c0-14.524 14.301-26.295 31.931-26.295 17.63 0 31.932 11.777 31.932 26.295v10.153z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/log.svg b/jcdm-ui/src/assets/icons/svg/log.svg
new file mode 100644
index 0000000..d879d33
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/log.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1566035943711" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4805" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M208.736 566.336H64.384v59.328h144.352v-59.328z m0-336.096H165.44V74.592c0-7.968 4.896-14.848 10.464-14.848h502.016V0.448H175.936c-38.72 1.248-69.248 34.368-68.192 74.144v155.648H64.384V289.6h144.352V230.24z m0 168.096H64.384v59.328h144.352v-59.328z m714.656 76.576h-57.76v474.496c0 7.936-4.896 14.848-10.464 14.848H175.936c-5.568 0-10.464-6.912-10.464-14.848v-155.68h43.296v-59.296H64.384v59.296h43.328v155.68c-1.024 39.776 29.472 72.896 68.192 74.144h679.232c38.72-1.184 69.248-34.368 68.256-74.144V474.912z m14.944-290.336l-83.072-85.312a71.264 71.264 0 0 0-52.544-21.728 71.52 71.52 0 0 0-51.616 23.872L386.528 507.264a30.496 30.496 0 0 0-6.176 10.72L308.16 740.512a30.016 30.016 0 0 0 6.976 30.24c7.712 7.968 19.2 10.752 29.568 7.2l216.544-74.112a28.736 28.736 0 0 0 12.128-7.936L940.448 287.456a75.552 75.552 0 0 0-2.112-102.88z m-557.12 518.272l39.104-120.64 78.336 80.416-117.44 40.224z m170.048-70.016l-103.552-106.016 200.16-222.4 103.52 106.304-200.128 222.112zM897.952 247.072l-0.256 0.224-107.136 119.168-103.52-106.528 106.432-118.624a14.144 14.144 0 0 1 10.304-4.736 13.44 13.44 0 0 1 10.464 4.288l83.264 85.696c5.472 5.6 5.664 14.72 0.448 20.512z" p-id="4806"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/logininfor.svg b/jcdm-ui/src/assets/icons/svg/logininfor.svg
new file mode 100644
index 0000000..267f844
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/logininfor.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1566036016814" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5261" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M896 128h-85.333333a42.666667 42.666667 0 0 0 0 85.333333h42.666666v640H170.666667V213.333333h42.666666a42.666667 42.666667 0 0 0 0-85.333333H128a42.666667 42.666667 0 0 0-42.666667 42.666667v725.333333a42.666667 42.666667 0 0 0 42.666667 42.666667h768a42.666667 42.666667 0 0 0 42.666667-42.666667V170.666667a42.666667 42.666667 0 0 0-42.666667-42.666667z" p-id="5262"></path><path d="M341.333333 298.666667a42.666667 42.666667 0 0 0 42.666667-42.666667V128a42.666667 42.666667 0 0 0-85.333333 0v128a42.666667 42.666667 0 0 0 42.666666 42.666667zM512 298.666667a42.666667 42.666667 0 0 0 42.666667-42.666667V128a42.666667 42.666667 0 0 0-85.333334 0v128a42.666667 42.666667 0 0 0 42.666667 42.666667zM682.666667 298.666667a42.666667 42.666667 0 0 0 42.666666-42.666667V128a42.666667 42.666667 0 0 0-85.333333 0v128a42.666667 42.666667 0 0 0 42.666667 42.666667zM341.333333 768a42.666667 42.666667 0 0 0 42.666667-42.666667 128 128 0 0 1 256 0 42.666667 42.666667 0 0 0 85.333333 0 213.333333 213.333333 0 0 0-107.52-184.32A128 128 0 0 0 640 469.333333a128 128 0 0 0-256 0 128 128 0 0 0 22.186667 71.68A213.333333 213.333333 0 0 0 298.666667 725.333333a42.666667 42.666667 0 0 0 42.666666 42.666667z m128-298.666667a42.666667 42.666667 0 1 1 42.666667 42.666667 42.666667 42.666667 0 0 1-42.666667-42.666667z" p-id="5263"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/message.svg b/jcdm-ui/src/assets/icons/svg/message.svg
new file mode 100644
index 0000000..14ca817
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/message.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M0 20.967v59.59c0 11.59 8.537 20.966 19.075 20.966h28.613l1 26.477L76.8 101.523h32.125c10.538 0 19.075-9.377 19.075-20.966v-59.59C128 9.377 119.463 0 108.925 0h-89.85C8.538 0 0 9.377 0 20.967zm82.325 33.1c0-5.524 4.013-9.935 9.037-9.935 5.026 0 9.038 4.41 9.038 9.934 0 5.524-4.025 9.934-9.038 9.934-5.024 0-9.037-4.41-9.037-9.934zm-27.613 0c0-5.524 4.013-9.935 9.038-9.935s9.037 4.41 9.037 9.934c0 5.524-4.025 9.934-9.037 9.934-5.025 0-9.038-4.41-9.038-9.934zm-27.1 0c0-5.524 4.013-9.935 9.038-9.935s9.038 4.41 9.038 9.934c0 5.524-4.026 9.934-9.05 9.934-5.013 0-9.025-4.41-9.025-9.934z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/money.svg b/jcdm-ui/src/assets/icons/svg/money.svg
new file mode 100644
index 0000000..c1580de
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/money.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M54.122 127.892v-28.68H7.513V87.274h46.609v-12.4H7.513v-12.86h38.003L.099 0h22.6l32.556 45.07c3.617 5.144 6.44 9.611 8.487 13.385 1.788-3.05 4.89-7.779 9.301-14.186L103.93 0h24.01L82.385 62.013h38.34v12.862h-46.41v12.4h46.41v11.937h-46.41v28.68H54.123z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/monitor.svg b/jcdm-ui/src/assets/icons/svg/monitor.svg
new file mode 100644
index 0000000..bc308cb
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/monitor.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1543827393750" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4695" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css">@font-face { font-family: rbicon; src: url("chrome-extension://dipiagiiohfljcicegpgffpbnjmgjcnf/fonts/rbicon.woff2") format("woff2"); font-weight: normal; font-style: normal; }
+</style></defs><path d="M64 64V640H896V64H64zM0 0h960v704H0V0z" p-id="4696"></path><path d="M192 896H768v64H192zM448 640H512v256h-64z" p-id="4697"></path><path d="M479.232 561.604267l309.9904-348.330667-47.803733-42.5472-259.566934 291.669333L303.957333 240.008533 163.208533 438.6048l52.224 37.009067 91.6224-129.28z" p-id="4698"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/nested.svg b/jcdm-ui/src/assets/icons/svg/nested.svg
new file mode 100644
index 0000000..06713a8
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/nested.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M.002 9.2c0 5.044 3.58 9.133 7.998 9.133 4.417 0 7.997-4.089 7.997-9.133 0-5.043-3.58-9.132-7.997-9.132S.002 4.157.002 9.2zM31.997.066h95.981V18.33H31.997V.066zm0 45.669c0 5.044 3.58 9.132 7.998 9.132 4.417 0 7.997-4.088 7.997-9.132 0-3.263-1.524-6.278-3.998-7.91-2.475-1.63-5.524-1.63-7.998 0-2.475 1.632-4 4.647-4 7.91zM63.992 36.6h63.986v18.265H63.992V36.6zm-31.995 82.2c0 5.043 3.58 9.132 7.998 9.132 4.417 0 7.997-4.089 7.997-9.132 0-5.044-3.58-9.133-7.997-9.133s-7.998 4.089-7.998 9.133zm31.995-9.131h63.986v18.265H63.992V109.67zm0-27.404c0 5.044 3.58 9.133 7.998 9.133 4.417 0 7.997-4.089 7.997-9.133 0-3.263-1.524-6.277-3.998-7.909-2.475-1.631-5.524-1.631-7.998 0-2.475 1.632-4 4.646-4 7.91zm31.995-9.13h31.991V91.4H95.987V73.135z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/number.svg b/jcdm-ui/src/assets/icons/svg/number.svg
new file mode 100644
index 0000000..ad5ce9a
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/number.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1575802851180" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2867" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M279.272727 791.272727h512a46.545455 46.545455 0 0 1 0 93.090909H279.272727a46.545455 46.545455 0 0 1 0-93.090909z m33.838546-617.984V651.636364H193.722182V395.170909c0-37.003636-0.884364-59.298909-2.653091-66.746182a24.948364 24.948364 0 0 0-14.615273-16.989091c-8.005818-3.863273-25.786182-5.771636-53.341091-5.771636h-11.822545v-55.854545c57.716364-12.381091 101.562182-37.888 131.490909-76.520728h70.283636z m303.709091 396.8V651.636364H354.164364v-68.235637c77.777455-127.255273 124.043636-206.010182 138.705454-236.218182 14.661818-30.254545 22.016-53.853091 22.016-70.74909 0-13.032727-2.234182-22.714182-6.656-29.137455-4.421818-6.376727-11.170909-9.588364-20.247273-9.588364a22.248727 22.248727 0 0 0-20.200727 10.612364c-4.468364 7.121455-6.656 21.178182-6.656 42.263273v45.521454H354.164364v-17.454545c0-26.763636 1.396364-47.941818 4.142545-63.348364 2.746182-15.499636 9.541818-30.72 20.386909-45.661091 10.798545-14.987636 24.901818-26.298182 42.216727-33.978182 17.361455-7.68 38.167273-11.543273 62.37091-11.543272 47.476364 0 83.316364 11.776 107.706181 35.328 24.296727 23.552 36.445091 53.341091 36.445091 89.367272 0 27.368727-6.842182 56.32-20.48 86.853819-13.730909 30.533818-54.039273 95.325091-121.018182 194.420363h130.885819z m270.615272-189.393454c18.152727 6.097455 31.650909 16.104727 40.494546 29.975272 8.843636 13.917091 13.312 46.452364 13.312 97.652364 0 38.027636-4.328727 67.490909-13.032727 88.529455-8.657455 20.945455-23.598545 36.910545-44.869819 47.848727-21.271273 10.938182-48.593455 16.384-81.873454 16.384-37.794909 0-67.490909-6.330182-89.088-19.083636-21.550545-12.660364-35.746909-28.253091-42.542546-46.638546-6.795636-18.432-10.193455-50.362182-10.193454-95.883636v-37.841455h119.389091v77.730909c0 20.666182 1.210182 33.838545 3.723636 39.424 2.420364 5.585455 7.912727 8.424727 16.337455 8.424728 9.309091 0 15.36-3.537455 18.338909-10.612364 2.932364-7.121455 4.421818-25.6 4.421818-55.575273v-33.047273c0-18.338909-2.048-31.744-6.190546-40.215272a30.72 30.72 0 0 0-18.338909-16.709818c-8.052364-2.653091-23.738182-4.189091-46.964363-4.561455V357.050182c28.392727 0 45.893818-1.070545 52.596363-3.258182a22.946909 22.946909 0 0 0 14.475637-14.149818c2.932364-7.307636 4.421818-18.711273 4.421818-34.257455v-26.624c0-16.756364-1.722182-27.741091-5.12-33.047272-3.490909-5.352727-8.843636-8.005818-16.151273-8.005819-8.285091 0-13.963636 2.792727-16.989091 8.378182-3.025455 5.632-4.561455 17.640727-4.561454 35.933091v39.284364h-119.389091v-40.773818c0-45.661091 10.472727-76.567273 31.325091-92.625455 20.898909-16.058182 54.085818-24.064 99.607272-24.064 56.878545 0 95.511273 11.170909 115.805091 33.373091 20.293818 22.248727 30.394182 53.201455 30.394182 92.765091 0 26.810182-3.630545 46.173091-10.891636 58.088727-7.307636 11.915636-20.107636 22.807273-38.446546 32.628364z" p-id="2868"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/online.svg b/jcdm-ui/src/assets/icons/svg/online.svg
new file mode 100644
index 0000000..330a202
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/online.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1568899557259" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="535" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M356.246145 681.56286c-68.156286-41.949414-107.246583-103.84102-107.246583-169.805384 0-65.966411 39.090297-127.860063 107.246583-169.809477 12.046361-7.414877 15.800871-23.190165 8.385994-35.236526-7.413853-12.046361-23.191188-15.801894-35.236526-8.387018-39.640836 24.399713-72.539106 56.044434-95.137801 91.515297-23.86657 37.461193-36.481889 79.620385-36.481889 121.917724 0 42.297338 12.615319 84.454484 36.481889 121.914654 22.598694 35.469839 55.496965 67.11456 95.137801 91.51325 4.185322 2.576685 8.821923 3.804652 13.400195 3.804652 8.598842 0 16.998139-4.329609 21.836331-12.190647C372.047016 704.752002 368.291482 688.976714 356.246145 681.56286zM263.943926 754.580874c-92.603071-61.111846-145.713686-149.623739-145.713686-242.840794 0-93.195565 53.094242-181.682899 145.667637-242.774279 11.805884-7.79043 15.061021-23.677259 7.269567-35.483142-7.79043-11.805884-23.677259-15.062044-35.483142-7.269567C128.487861 296.954249 67.006602 401.024489 67.006602 511.74008c0 110.73708 61.496609 214.830857 168.721703 285.593504 4.343935 2.867304 9.240455 4.238534 14.08274 4.238534 8.317433 0 16.476253-4.046153 21.400403-11.507078C279.003923 778.258133 275.748786 762.372328 263.943926 754.580874zM788.660552 226.213092c-11.80486-7.791453-27.692712-4.536316-35.483142 7.269567-7.79043 11.805884-4.536316 27.692712 7.269567 35.483142 92.575442 61.092403 145.670707 149.579737 145.670707 242.774279 0 93.216032-53.111638 181.727924-145.715733 242.840794-11.805884 7.79043-15.059997 23.678282-7.269567 35.484166 4.925173 7.461949 13.081946 11.507078 21.400403 11.507078 4.841262 0 9.739828-1.37123 14.083763-4.238534 107.22714-70.761624 168.724773-174.857447 168.724773-285.593504C957.341323 401.025513 895.860063 296.955272 788.660552 226.213092zM790.090111 633.67213c23.865547-37.459147 36.480866-79.617315 36.480866-121.914654 0-42.298362-12.615319-84.45653-36.480866-121.917724-22.598694-35.470863-55.496965-67.115584-95.139847-91.515297-12.047384-7.413853-27.821649-3.659343-35.236526 8.387018-7.414877 12.045337-3.659343 27.821649 8.385994 35.236526 68.156286 41.949414 107.247606 103.842043 107.247606 169.809477 0 65.964364-39.090297 127.85597-107.247606 169.804361-12.045337 7.414877-15.800871 23.190165-8.385994 35.237549 4.838192 7.861038 13.236466 12.190647 21.835308 12.190647 4.579295 0 9.215896-1.227967 13.400195-3.804652C734.591099 700.786691 767.490394 669.142993 790.090111 633.67213zM567.129086 518.274914c24.12342-17.150612 39.887452-45.305859 39.887452-77.07133 0-52.128241-42.452881-94.538143-94.634334-94.538143-52.18043 0-94.633311 42.408879-94.633311 94.538143 0 31.695886 15.696494 59.797921 39.730886 76.958766-49.875944 21.128203-84.917018 70.234621-84.917018 127.301338 0 2.366907 0.061398 4.762467 0.182149 7.119141l1.249457 24.296359 276.373515 0 1.238201-24.308639c0.119727-2.358721 0.181125-4.750187 0.181125-7.106862C651.786185 588.497255 616.865861 539.465538 567.129086 518.274914zM512.381182 397.889079c23.937179 0 43.411719 19.430538 43.411719 43.314505 0 23.882943-19.47454 43.313481-43.411719 43.313481-23.936155 0-43.409672-19.430538-43.409672-43.313481C468.971509 417.320641 488.445026 397.889079 512.381182 397.889079zM426.08884 625.656573c9.119705-38.542828 44.254923-67.337641 86.085634-67.337641s76.966952 28.794813 86.085634 67.337641L426.08884 625.656573z" p-id="536"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/password.svg b/jcdm-ui/src/assets/icons/svg/password.svg
new file mode 100644
index 0000000..6c64def
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/password.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1575802846045" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2750" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M868.593046 403.832442c-30.081109-28.844955-70.037123-44.753273-112.624057-44.753273L265.949606 359.079168c-42.554188 0-82.510202 15.908318-112.469538 44.690852-30.236652 28.782533-46.857191 67.222007-46.857191 108.198258l0 294.079782c0 40.977273 16.619516 79.414701 46.702672 108.136859 29.959336 28.844955 70.069869 44.814672 112.624057 44.814672l490.019383 0c42.585911 0 82.696444-15.969717 112.624057-44.814672 30.082132-28.844955 46.579875-67.222007 46.579875-108.136859L915.172921 511.968278C915.171897 471.053426 898.675178 432.677397 868.593046 403.832442zM841.821309 806.049083c0 22.098297-8.882298 42.772152-25.099654 58.306964-16.154935 15.661701-37.81935 24.203238-60.752666 24.203238L265.949606 888.559285c-22.934339 0-44.567032-8.54256-60.877509-24.264637-16.186657-15.474436-25.067932-36.148291-25.067932-58.246589L180.004165 511.968278c0-22.035876 8.881274-42.772152 25.192775-58.307987 16.186657-15.536858 37.81935-24.139793 60.753689-24.139793l490.019383 0c22.933315 0 44.597731 8.602935 60.752666 24.139793 16.21838 15.535835 25.099654 36.272112 25.099654 58.307987L841.822332 806.049083zM510.974136 135.440715c114.914216 0 208.318536 89.75214 208.318536 200.055338l73.350588 0c0-149.113109-126.366036-270.496667-281.669124-270.496667-155.333788 0-281.699824 121.383558-281.699824 270.496667l73.350588 0C302.623877 225.193879 396.059919 135.440715 510.974136 135.440715zM474.299865 747.244792l73.350588 0L547.650453 629.576859l-73.350588 0L474.299865 747.244792z" p-id="2751"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/pdf.svg b/jcdm-ui/src/assets/icons/svg/pdf.svg
new file mode 100644
index 0000000..957aa0c
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/pdf.svg
@@ -0,0 +1 @@
+<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="128" height="128"><path d="M869.073 277.307H657.111V65.344l211.962 211.963zm-238.232 26.27V65.344l-476.498-.054v416.957h714.73v-178.67H630.841zm-335.836 360.57c-5.07-3.064-10.944-5.133-17.61-6.201-6.67-1.064-13.603-1.6-20.81-1.6h-48.821v85.641h48.822c7.206 0 14.14-.532 20.81-1.6 6.665-1.065 12.54-3.133 17.609-6.202 5.064-3.063 9.134-7.406 12.208-13.007 3.065-5.602 4.6-12.937 4.6-22.011 0-9.07-1.535-16.408-4.6-22.01-3.074-5.603-7.144-9.94-12.208-13.01zM35.82 541.805v416.904h952.358V541.805H35.821zm331.421 191.179c-3.6 11.071-9.343 20.879-17.209 29.413-7.874 8.542-18.078 15.408-30.617 20.61-12.544 5.206-27.747 7.807-45.621 7.807h-66.036v102.45h-62.831V607.517h128.867c17.874 0 33.077 2.6 45.62 7.802 12.541 5.207 22.745 12.076 30.618 20.615 7.866 8.538 13.604 18.277 17.21 29.212 3.6 10.943 5.401 22.278 5.401 34.018 0 11.477-1.8 22.752-5.402 33.819zM644.9 806.417c-5.343 17.61-13.408 32.818-24.212 45.627-10.807 12.803-24.283 22.879-40.423 30.213-16.146 7.343-35.155 11.007-57.03 11.007h-123.26V607.518h123.26c18.41 0 35.552 2.941 51.428 8.808 15.873 5.869 29.618 14.671 41.22 26.412 11.608 11.744 20.674 26.411 27.217 44.02 6.535 17.61 9.803 38.288 9.803 62.035 0 20.81-2.67 40.02-8.003 57.624zm245.362-146.07h-138.07v66.03h119.66v48.829h-119.66v118.058h-62.83V607.518h200.9v52.829h-.001zm-318.2 25.611c-6.402-8.266-14.877-14.604-25.412-19.01-10.544-4.402-23.551-6.602-39.019-6.602h-44.825v180.088h56.029c9.07 0 17.872-1.463 26.415-4.401 8.535-2.932 16.14-7.802 22.812-14.609 6.665-6.8 12.007-15.667 16.007-26.61 4.003-10.94 6.003-24.275 6.003-40.021 0-14.408-1.4-27.416-4.202-39.019-2.8-11.607-7.406-21.542-13.808-29.816zm0 0"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/people.svg b/jcdm-ui/src/assets/icons/svg/people.svg
new file mode 100644
index 0000000..2bd54ae
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/people.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M104.185 95.254c8.161 7.574 13.145 17.441 13.145 28.28 0 1.508-.098 2.998-.285 4.466h-10.784c.238-1.465.403-2.948.403-4.465 0-8.983-4.36-17.115-11.419-23.216C86 104.66 75.355 107.162 64 107.162c-11.344 0-21.98-2.495-31.22-6.83-7.064 6.099-11.444 14.218-11.444 23.203 0 1.517.165 3 .403 4.465H10.955a35.444 35.444 0 0 1-.285-4.465c0-10.838 4.974-20.713 13.127-28.291C9.294 85.42.003 70.417.003 53.58.003 23.99 28.656.001 64 .001s63.997 23.988 63.997 53.58c0 16.842-9.299 31.85-23.812 41.673zM64 36.867c-29.454 0-53.33-10.077-53.33 15.342 0 25.418 23.876 46.023 53.33 46.023 29.454 0 53.33-20.605 53.33-46.023 0-25.419-23.876-15.342-53.33-15.342zm24.888 25.644c-3.927 0-7.111-2.665-7.111-5.953 0-3.288 3.184-5.954 7.11-5.954 3.928 0 7.111 2.666 7.111 5.954s-3.183 5.953-7.11 5.953zm-3.556 16.372c0 4.11-9.55 7.442-21.332 7.442-11.781 0-21.332-3.332-21.332-7.442 0-1.06.656-2.064 1.8-2.976 3.295 2.626 10.79 4.465 19.532 4.465 8.743 0 16.237-1.84 19.531-4.465 1.145.912 1.801 1.916 1.801 2.976zm-46.22-16.372c-3.927 0-7.11-2.665-7.11-5.953 0-3.288 3.183-5.954 7.11-5.954 3.927 0 7.111 2.666 7.111 5.954s-3.184 5.953-7.11 5.953z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/peoples.svg b/jcdm-ui/src/assets/icons/svg/peoples.svg
new file mode 100644
index 0000000..aab852e
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/peoples.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M95.648 118.762c0 5.035-3.563 9.121-7.979 9.121H7.98c-4.416 0-7.979-4.086-7.979-9.121C0 100.519 15.408 83.47 31.152 76.75c-9.099-6.43-15.216-17.863-15.216-30.987v-9.128c0-20.16 14.293-36.518 31.893-36.518s31.894 16.358 31.894 36.518v9.122c0 13.137-6.123 24.556-15.216 30.993 15.738 6.726 31.141 23.769 31.141 42.012z"/><path d="M106.032 118.252h15.867c3.376 0 6.101-3.125 6.101-6.972 0-13.957-11.787-26.984-23.819-32.123 6.955-4.919 11.638-13.66 11.638-23.704v-6.985c0-15.416-10.928-27.926-24.39-27.926-1.674 0-3.306.193-4.89.561 1.936 4.713 3.018 9.974 3.018 15.526v9.121c0 13.137-3.056 23.111-11.066 30.993 14.842 4.41 27.312 23.42 27.541 41.509z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/phone.svg b/jcdm-ui/src/assets/icons/svg/phone.svg
new file mode 100644
index 0000000..ab8e8c4
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/phone.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1567417214476" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2266" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M761.503029 2.90619 242.121921 2.90619c-32.405037 0-58.932204 26.060539-58.932204 58.527998l0 902.302287c0 32.156374 26.217105 58.216913 58.932204 58.216913l519.381108 0c32.344662 0 58.591443-26.060539 58.591443-58.216913L820.094472 61.123103C820.094472 28.966729 793.847691 2.90619 761.503029 2.90619M452.878996 61.123103l98.147344 0c6.780427 0 12.31549 5.536087 12.31549 12.253068 0 6.748704-5.535063 12.253068-12.31549 12.253068l-98.147344 0c-6.779404 0-12.345166-5.504364-12.345166-12.253068C440.532807 66.659189 446.099592 61.123103 452.878996 61.123103M501.641583 980.593398c-29.636994 0-53.987588-23.946388-53.987588-53.677527 0-29.356608 24.039509-53.614082 53.987588-53.614082 29.91738 0 53.987588 23.883967 53.987588 53.614082C555.629171 956.647009 531.559986 980.593398 501.641583 980.593398M766.35657 803.142893c0 16.23373-13.186324 29.107945-29.233811 29.107945l-470.618521 0c-16.35755 0-29.325909-13.186324-29.325909-29.107945L237.178329 163.500794c0-16.232706 13.279445-29.138644 29.325909-29.138644l470.246037 0c16.420995 0 29.357632 13.1853 29.357632 29.138644l0 639.642099L766.35657 803.142893zM766.35657 803.142893" p-id="2267"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/post.svg b/jcdm-ui/src/assets/icons/svg/post.svg
new file mode 100644
index 0000000..2922c61
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/post.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1566035724641" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3998" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M136.4 434.3h77.7c21.5 0 38.9-17.4 38.9-38.9s-17.4-38.9-38.9-38.9h-77.7c-21.5 0-38.9 17.4-38.9 38.9s17.4 38.9 38.9 38.9zM252.9 628.6c0-21.5-17.4-38.9-38.9-38.9h-77.7c-21.5 0-38.9 17.4-38.9 38.9s17.4 38.9 38.9 38.9H214c21.5-0.1 38.9-17.5 38.9-38.9z" p-id="3999"></path><path d="M874.7 97.5H227c-28.6 0-51.8 23.2-51.8 51.8v194.3h38.9c28.6 0 51.8 23.2 51.8 51.8 0 28.6-23.2 51.8-51.8 51.8h-38.9v129.5h38.9c28.6 0 51.8 23.2 51.8 51.8 0 28.6-23.2 51.8-51.8 51.8h-38.9v194.3c0 28.6 23.2 51.8 51.8 51.8h647.7c28.6 0 51.8-23.2 51.8-51.8V149.3c0-28.6-23.2-51.8-51.8-51.8z m-311.3 723c-15.6 0-146.7-71.6-146.7-91 0-19.4 102-368.6 102-368.6l-83.6-104s-12.3-23.1 24.6-23.1h208.9c36.9 0 18.4 23.1 18.4 23.1l-79 104s102 351.3 102 368.6c0.1 17.3-131 91-146.6 91z m169.2-253.6l-27.9 40.2-74.5-240 103.4 171.7c4.6 7.9 4.2 20.6-1 28.1z" p-id="4000"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/qq.svg b/jcdm-ui/src/assets/icons/svg/qq.svg
new file mode 100644
index 0000000..ee13d4e
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/qq.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M18.448 57.545l-.244-.744-.198-.968-.132-.53v-2.181l.236-.859.24-.908.317-.953.428-1.06.561-1.103.794-1.104v-.773l.077-.724.123-.984.34-1.106.313-1.194.25-.548.289-.511.371-.569.405-.423v-2.73l.234-1.407.236-1.633.42-1.955.577-2.035.43-1.118.426-1.217.468-1.135.559-1.216.57-1.332.655-1.247.737-1.331.929-1.33.43-.762.457-.624.995-1.406 1.025-1.403 1.163-1.444 1.246-1.405 1.352-1.384 1.41-1.423 1.708-1.536 1.083-.934 1.322-1.008 1.34-.89 1.448-.855 1.392-.76 1.57-.63 1.667-.775 1.657-.532 1.653-.552 1.787-.548 1.785-.417 1.876-.347L59.128.68l1.879-.245 1.876-.252 2.002-.106h5.912l1.97.243 1.981.231 2.019.207 1.874.441 1.979.413 1.857.475 2.035.53 1.862.646 1.782.738 1.904.78 1.736.853 1.689.95 1.655 1.044 1.425.971.662.548.693.401 1.323 1.1 1.115 1.064 1.112 1.1 1.083 1.214.894 1.178 1.064 1.217.74 1.306.752 1.162.798 1.352.661 1.175 1.113 2.489.546 1.286.428 1.192.428 1.294.384 1.217.267 1.047.347 1.231.607 2.198.388 1.924.253 1.861.217 1.497.342 2.28.077.362.274.41.737 1.18.473.8.42.832.534.892.472 1.07.307 1.093.334 1.2.252 1.232.115.605.106.746v.648l-.106.643v.8l-.192.774-.35 1.5-.403.76-.299.852v.213l.142.264.4.623 1.746 2.53 1.377 1.9.66 1.267.889 1.389.774 1.52.893 1.627.894 1.828 1.006 2.069.567 1.268.518 1.239.447 1.307.44 1.175.336 1.235.342 1.16.432 2.261.343 2.31.235 2.05v2.891l-.158 1.025-.226 1.768-.308 1.59-.48 1.44-.18.588-.336.707-.28.493-.375.607-.33.383-.42.494-.375.4-.401.34-.48.207-.432.207-.355.114h-.543l-.346-.114-.66-.32-.302-.212-.317-.223-.347-.304-.35-.342-.579-.63-.684-.89-.539-.917-.538-.734-.526-.855-.741-1.517-.833-1.579-.098-.055h-.138l-.338.247-.196.415-.326.516-.567 1.533-.856 2.182-1.096 2.626-.824 1.308-.864 1.366-1.027 1.536-1.09 1.503-.557.68-.676.743-1.555 1.497.136.135.21.214.777.446 3.235 1.524 1.41.779 1.347.756 1.332.953 1.187.982.574.443.432.511.445.593.367.643.198.533.242.64.105.554.115.647-.115.433v.44l-.105.454-.242.415-.092.325-.22.394-.587.784-.543.627-.42.47-.35.348-.893.638-1.01.556-1.077.532-1.155.511-1.287.495-.693.207-.608.167-1.496.342-1.545.325-1.552.323-1.689.27-1.74.072-1.785.21h-5.539l-1.998-.114-1.86-.168-2.005-.27-1.99-.209-2.095-.286-2.03-.495-1.981-.374-1.968-.552-2.019-.707-1.98-.585-1.044-.342-.927-.323-.586-.223-.582-.12h-1.647l-1.904-.131-.962-.096-1.24-.135-.795.705-1.085.665-1.471.701-1.628.875-.99.475-1.033.376-2.281.914-1.24.305-1.3.343-1.803.344-1.13.086-1.193.1-1.246.135-1.45.053h-5.926l-3.346-.053-3.25-.321-1.644-.23-1.589-.23-1.546-.227-1.547-.305-1.442-.456-1.434-.325-1.294-.51-1.223-.474-1.142-.533-.99-.583-.984-.71-.336-.343-.44-.415-.334-.362-.3-.417-.278-.415-.215-.42-.311-.89-.109-.46-.138-.51v-.473l.138-.533v-.53l.109-.53v-1.069l.052-.564.259-.647.215-.646.39-.779.286-.3.236-.348.615-.738.49-.38.464-.266.428-.338.676-.21.543-.324.676-.341.77-.227.775-.231.897-.192.85-.11 1.008-.13 1.093-.081.284-.092h.063l.137-.115v-.13l-.2-.266-.58-.27-1.45-1.231-.975-.761-1.127-.967-1.136-1.082-1.181-1.382-1.36-1.558-.508-.843-.672-.87-.58-1.007-.522-1.1-.704-1.047-.459-1.194-.547-1.192-.546-1.33-.397-1.273-.378-1.575-.112-.057h-.115l-.059-.113h-.14l-.23.113-.114.057-.158.264-.057.321-.119.286-.206.477-.664 1.157-.345.701-.546.612-.58.736-.641.816-.677.724-.795.701-.734.658-.814.524-.89.546-.855.325-1.008.247-.99.095h-.233l-.228-.095-.18-.384-.29-.188-.38-.912-.237-.493-.255-.707-.21-.734-.113-.724-.313-1.648-.12-.972v-3.185l.12-2.379.196-1.214.23-1.252.21-1.347.374-1.254.42-1.443.431-1.407.578-1.448.545-1.38.754-1.4.699-1.52.855-1.425 1.006-1.538 1.023-1.382 1.069-1.538.891-1.071 1.142-1.227 1.202-1.237.56-.59.678-.662.985-.836 1.012-.853 1.647-1.446 1.242-.889z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/question.svg b/jcdm-ui/src/assets/icons/svg/question.svg
new file mode 100644
index 0000000..cf75bd4
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/question.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1581238842264" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1409" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M512 0C229.233778 0 0 229.233778 0 512s229.233778 512 512 512 512-229.233778 512-512A512 512 0 0 0 512 0z m0 938.666667C276.366222 938.666667 85.333333 747.633778 85.333333 512 85.333333 276.366222 276.366222 85.333333 512 85.333333c235.633778 0 426.666667 191.032889 426.666667 426.666667a426.666667 426.666667 0 0 1-426.666667 426.666667z m0-717.653334a170.666667 170.666667 0 0 0-170.666667 170.666667 42.666667 42.666667 0 0 0 85.333334 0 85.333333 85.333333 0 1 1 85.333333 85.333333 42.666667 42.666667 0 0 0-42.666667 42.666667v111.36a42.666667 42.666667 0 0 0 85.333334 0v-74.24A170.666667 170.666667 0 0 0 512 221.013333z m-42.666667 542.293334a42.666667 42.666667 0 1 0 85.333334 0 42.666667 42.666667 0 0 0-85.333334 0z" p-id="1410"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/radio.svg b/jcdm-ui/src/assets/icons/svg/radio.svg
new file mode 100644
index 0000000..0cde345
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/radio.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1575966775973" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="879" xmlns:xlink="http://www.w3.org/1999/xlink" width="81" height="81"><defs><style type="text/css"></style></defs><path d="M507.39346659 71.84873358c241.53533667 0 437.39770766 195.85422109 437.39770767 437.37442191 0 241.53766571-195.86237099 437.38955776-437.39770767 437.38955776-241.50040803 0-437.34997219-195.85189205-437.34997219-437.38955776C70.0434944 267.70295467 265.89189347 71.84873358 507.39346659 71.84873358L507.39346659 71.84873358zM507.39346659 282.81899805c-125.00686734 0-226.37039389 101.38914133-226.37039388 226.41813048 0 125.01268821 101.36352768 226.39717262 226.37039388 226.39717262 125.04295993 0 226.42395136-101.38448441 226.42395136-226.39717262C733.81625401 384.20813938 632.43642653 282.81899805 507.39346659 282.81899805L507.39346659 282.81899805zM507.39346659 120.78172615c-214.46664192 0-388.42047261 173.95150279-388.4204726 388.44026539 0 214.51204949 173.95499463 388.46122325 388.4204726 388.46122325 214.52369237 0 388.46005817-173.94800981 388.46005818-388.46122325C895.85236082 294.73322894 721.91715897 120.78172615 507.39346659 120.78172615z" p-id="880"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/rate.svg b/jcdm-ui/src/assets/icons/svg/rate.svg
new file mode 100644
index 0000000..aa3b14d
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/rate.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1577246781606" class="icon" viewBox="0 0 1069 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1098" xmlns:xlink="http://www.w3.org/1999/xlink" width="84.5595703125" height="81"><defs><style type="text/css"></style></defs><path d="M633.72929961 378.02038203l9.49872568 18.68789795 20.78025469 2.79745225 206.61592412 27.33248408a11.46496817 11.46496817 0 0 1 6.6095543 19.47324902l-147.2675168 147.35350284-14.89299345 14.89299345 3.8006376 20.68280244 37.84585956 204.89044571a11.46496817 11.46496817 0 0 1-16.4808914 12.2961788L554.68980898 751.84713388l-18.68789794-9.49299345-18.48726123 9.99171915-183.23885392 99.34968163a11.46496817 11.46496817 0 0 1-16.78471347-11.8662416l32.5433127-205.79617881 3.29617793-20.78598692-15.19108243-14.49172002-151.03375839-143.48407587a11.46496817 11.46496817 0 0 1 6.09936328-19.63949062l205.79617881-32.63503185 20.78598691-3.2961788L428.87898125 380.72038203 518.59235674 192.64331182a11.46496817 11.46496817 0 0 1 20.56815264-0.26369385l94.56879023 185.63503183zM496.64840732 85.52038203l-121.75796162 254.98089229L95.76433145 384.76178369A34.3949045 34.3949045 0 0 0 77.46050938 443.66879023l204.87324901 194.66369385-44.16879023 279.1146498a34.3949045 34.3949045 0 0 0 50.36560489 35.61592325l248.4-134.67898038 251.84522285 128.27579591a34.3949045 34.3949045 0 0 0 49.43694287-36.89426777l-51.30573223-277.85350284 199.73120977-199.90891758a34.3949045 34.3949045 0 0 0-19.82866201-58.40827998l-280.11783428-37.03184736L558.32993633 84.71210205a34.3949045 34.3949045 0 0 0-61.68152901 0.80254775z" p-id="1099"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/redis-list.svg b/jcdm-ui/src/assets/icons/svg/redis-list.svg
new file mode 100644
index 0000000..98a15b2
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/redis-list.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1656035183065" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3395" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css">@font-face { font-family: feedback-iconfont; src: url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff2?t=1630033759944") format("woff2"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff?t=1630033759944") format("woff"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.ttf?t=1630033759944") format("truetype"); }
+</style></defs><path d="M958.88 730.06H65.12c-18.28 0-33.12-14.82-33.12-33.12V68.91c0-18.29 14.83-33.12 33.12-33.12h893.77c18.28 0 33.12 14.82 33.12 33.12v628.03c-0.01 18.3-14.84 33.12-33.13 33.12zM98.23 663.83h827.53v-561.8H98.23v561.8z" p-id="3396"></path><path d="M512 954.55c-18.28 0-33.12-14.82-33.12-33.12V733.92c0-18.29 14.83-33.12 33.12-33.12s33.12 14.82 33.12 33.12v187.51c0 18.3-14.84 33.12-33.12 33.12z" p-id="3397"></path><path d="M762.01 988.21H261.99c-18.28 0-33.12-14.82-33.12-33.12 0-18.29 14.83-33.12 33.12-33.12h500.03c18.28 0 33.12 14.82 33.12 33.12-0.01 18.29-14.84 33.12-33.13 33.12zM514.74 578.55c-21.63 0-43.31-3.87-64.21-11.65-45.95-17.13-82.49-51.13-102.86-95.74-5.07-11.08-0.19-24.19 10.89-29.26 11.08-5.09 24.19-0.18 29.26 10.91 15.5 33.88 43.25 59.7 78.14 72.71 34.93 12.99 72.79 11.64 106.66-3.85 33.22-15.17 58.8-42.26 72.03-76.3 4.42-11.37 17.21-17.01 28.57-12.58 11.36 4.42 16.99 17.22 12.57 28.58-17.42 44.82-51.1 80.5-94.82 100.47-24.34 11.12-50.25 16.71-76.23 16.71z" p-id="3398"></path><path d="M325.27 528.78c-1.66 0-3.34-0.18-5.02-0.57-11.88-2.77-19.28-14.63-16.49-26.51l18.84-81c1.34-5.82 5-10.84 10.13-13.92 5.09-3.09 11.3-3.96 17.03-2.41l80.51 21.43c11.79 3.14 18.8 15.23 15.67 27.02-3.15 11.79-15.42 18.75-27.02 15.65l-58.49-15.57-13.69 58.81c-2.37 10.2-11.45 17.07-21.47 17.07zM360.8 351.01c-2.65 0-5.37-0.49-8-1.51-11.36-4.41-16.99-17.21-12.59-28.57 17.4-44.79 51.06-80.47 94.8-100.48 92.15-42.06 201.25-1.39 243.31 90.68 5.07 11.08 0.19 24.19-10.89 29.26-11.13 5.07-24.19 0.17-29.26-10.91-31.97-69.91-114.9-100.82-184.79-68.86-33.22 15.19-58.8 42.28-71.99 76.29-3.41 8.74-11.75 14.1-20.59 14.1z" p-id="3399"></path><path d="M684.68 376.74c-1.47 0-2.95-0.15-4.42-0.44l-81.61-16.68c-11.94-2.45-19.64-14.11-17.21-26.06 2.44-11.96 14.1-19.64 26.04-17.22l59.29 12.12 10.23-59.5c2.05-12 13.52-20.19 25.48-18.01 12.03 2.06 20.09 13.48 18.02 25.5l-14.08 81.96a22.089 22.089 0 0 1-9.29 14.49c-3.7 2.51-8.03 3.84-12.45 3.84z" p-id="3400"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/redis.svg b/jcdm-ui/src/assets/icons/svg/redis.svg
new file mode 100644
index 0000000..2f1d62d
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/redis.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1605865043777" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="856" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M1023.786667 611.84c-0.426667 9.770667-13.354667 20.693333-39.893334 34.56-54.613333 28.458667-337.749333 144.896-397.994666 176.298667-60.288 31.402667-93.738667 31.104-141.354667 8.32-47.616-22.741333-348.842667-144.469333-403.114667-170.368-27.093333-12.970667-40.917333-23.893333-41.386666-34.218667v103.509333c0 10.325333 14.250667 21.290667 41.386666 34.261334 54.272 25.941333 355.541333 147.626667 403.114667 170.368 47.616 22.784 81.066667 23.082667 141.354667-8.362667 60.245333-31.402667 343.338667-147.797333 397.994666-176.298667 27.776-14.464 40.106667-25.728 40.106667-35.925333v-102.058667l-0.213333-0.085333z m0-168.746667c-0.512 9.770667-13.397333 20.650667-39.893334 34.517334-54.613333 28.458667-337.749333 144.896-397.994666 176.298666-60.288 31.402667-93.738667 31.104-141.354667 8.362667-47.616-22.741333-348.842667-144.469333-403.114667-170.410667-27.093333-12.928-40.917333-23.893333-41.386666-34.176v103.509334c0 10.325333 14.250667 21.248 41.386666 34.218666 54.272 25.941333 355.498667 147.626667 403.114667 170.368 47.616 22.784 81.066667 23.082667 141.354667-8.32 60.245333-31.402667 343.338667-147.84 397.994666-176.298666 27.776-14.506667 40.106667-25.770667 40.106667-35.968v-102.058667l-0.256-0.042667z m0-175.018666c0.469333-10.410667-13.141333-19.541333-40.533334-29.610667-53.248-19.498667-334.634667-131.498667-388.522666-151.253333-53.888-19.712-75.818667-18.901333-139.093334 3.84C392.234667 113.706667 92.629333 231.253333 39.338667 252.074667c-26.666667 10.496-39.68 20.181333-39.253334 30.506666V386.133333c0 10.325333 14.250667 21.248 41.386667 34.218667 54.272 25.941333 355.498667 147.669333 403.114667 170.410667 47.616 22.741333 81.066667 23.04 141.354666-8.362667 60.245333-31.402667 343.338667-147.84 397.994667-176.298667 27.776-14.506667 40.106667-25.770667 40.106667-35.968V268.074667h-0.341334zM366.677333 366.08l237.269334-36.437333-71.68 105.088-165.546667-68.650667z m524.8-94.634667l-140.330666 55.466667-15.232 5.973333-140.245334-55.466666 155.392-61.44 140.373334 55.466666z m-411.989333-101.674666l-22.954667-42.325334 71.594667 27.989334 67.498667-22.101334-18.261334 43.733334 68.778667 25.770666-88.704 9.216-19.882667 47.786667-32.085333-53.290667-102.4-9.216 76.416-27.562666z m-176.768 59.733333c70.058667 0 126.805333 21.973333 126.805333 49.109333s-56.746667 49.152-126.805333 49.152-126.848-22.058667-126.848-49.152c0-27.136 56.789333-49.152 126.848-49.152z" p-id="857"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/row.svg b/jcdm-ui/src/assets/icons/svg/row.svg
new file mode 100644
index 0000000..0780992
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/row.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1579339929870" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1182" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M152 854.856875h325.7146875V237.715625H134.856875v600q0 6.99375 5.0746875 12.0684375T152 854.856875z m737.143125-17.1421875v-600H546.284375v617.1421875H872q6.99375 0 12.0684375-5.07375t5.0746875-12.0684375z m68.5715625-651.429375V837.715625q0 35.3821875-25.16625 60.5484375T872 923.4284375H152q-35.383125 0-60.5484375-25.1653125T66.284375 837.7146875V186.284375q0-35.3821875 25.16625-60.5484375T152 100.5715625h720q35.383125 0 60.5484375 25.1653125t25.16625 60.5484375z" p-id="1183"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/search.svg b/jcdm-ui/src/assets/icons/svg/search.svg
new file mode 100644
index 0000000..84233dd
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/search.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M124.884 109.812L94.256 79.166c-.357-.357-.757-.629-1.129-.914a50.366 50.366 0 0 0 8.186-27.59C101.327 22.689 78.656 0 50.67 0 22.685 0 0 22.688 0 50.663c0 27.989 22.685 50.663 50.656 50.663 10.186 0 19.643-3.03 27.6-8.201.286.385.557.771.9 1.114l30.628 30.632a10.633 10.633 0 0 0 7.543 3.129c2.728 0 5.457-1.043 7.543-3.115 4.171-4.157 4.171-10.915.014-15.073M50.671 85.338C31.557 85.338 16 69.78 16 50.663c0-19.102 15.557-34.661 34.67-34.661 19.115 0 34.657 15.559 34.657 34.675 0 19.102-15.557 34.661-34.656 34.661"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/select.svg b/jcdm-ui/src/assets/icons/svg/select.svg
new file mode 100644
index 0000000..d628382
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/select.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1575803481213" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="804" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M62 511.97954521C62 263.86590869 263.90681826 62 511.97954521 62s449.97954521 201.825 449.97954521 449.97954521c0 248.19545479-201.90681826 449.97954521-449.97954521 449.97954521C263.90681826 962 62 760.175 62 511.97954521M901.98636348 511.97954521c0-215.24318174-175.00909131-390.41590869-390.00681827-390.41590869-215.03863652 0-389.96590869 175.17272695-389.96590868 390.41590869 0 215.28409131 175.00909131 390.45681826 389.96590868 390.45681826C727.01818174 902.47727305 901.98636348 727.30454521 901.98636348 511.97954521M264.17272695 430.28409131c0-5.76818174 2.12727305-11.51590869 6.64772696-15.87272696 8.71363652-8.75454521 22.88863652-8.75454521 31.725 0l209.4340913 208.22727305L721.45454521 414.53409131c8.75454521-8.71363652 22.97045479-8.71363652 31.90909132 0 8.71363652 8.75454521 8.71363652 22.88863652 0 31.60227304L511.97954521 685.74090869 270.71818174 446.01363653C266.27954521 441.77954521 264.17272695 436.05227305 264.17272695 430.28409131" p-id="805"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/server.svg b/jcdm-ui/src/assets/icons/svg/server.svg
new file mode 100644
index 0000000..eb287e3
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/server.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1547360688278" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6717" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M890 120H134a70 70 0 0 0-70 70v500a70 70 0 0 0 70 70h756a70 70 0 0 0 70-70V190a70 70 0 0 0-70-70z m-10 520a40 40 0 0 1-40 40H712V448a40 40 0 0 0-80 0v232h-80V368a40 40 0 0 0-80 0v312h-80V512a40 40 0 0 0-80 0v168H184a40 40 0 0 1-40-40V240a40 40 0 0 1 40-40h656a40 40 0 0 1 40 40zM696 824H328a40 40 0 0 0 0 80h368a40 40 0 0 0 0-80z" p-id="6718"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/shopping.svg b/jcdm-ui/src/assets/icons/svg/shopping.svg
new file mode 100644
index 0000000..87513e7
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/shopping.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M42.913 101.36c1.642 0 3.198.332 4.667.996a12.28 12.28 0 0 1 3.89 2.772c1.123 1.184 1.987 2.582 2.592 4.193.605 1.612.908 3.318.908 5.118 0 1.8-.303 3.507-.908 5.118-.605 1.611-1.469 3.01-2.593 4.194a13.3 13.3 0 0 1-3.889 2.843 10.582 10.582 0 0 1-4.667 1.066c-1.729 0-3.306-.355-4.732-1.066a13.604 13.604 0 0 1-3.825-2.843c-1.123-1.185-1.988-2.583-2.593-4.194a14.437 14.437 0 0 1-.907-5.118c0-1.8.302-3.506.907-5.118.605-1.61 1.47-3.009 2.593-4.193a12.515 12.515 0 0 1 3.825-2.772c1.426-.664 3.003-.996 4.732-.996zm53.932.285c1.643 0 3.22.331 4.733.995a11.386 11.386 0 0 1 3.889 2.772c1.08 1.185 1.945 2.583 2.593 4.194.648 1.61.972 3.317.972 5.118 0 1.8-.324 3.506-.972 5.117-.648 1.611-1.513 3.01-2.593 4.194a12.253 12.253 0 0 1-3.89 2.843 11 11 0 0 1-4.732 1.066 10.58 10.58 0 0 1-4.667-1.066 12.478 12.478 0 0 1-3.824-2.843c-1.08-1.185-1.945-2.583-2.593-4.194a13.581 13.581 0 0 1-.973-5.117c0-1.801.325-3.507.973-5.118.648-1.611 1.512-3.01 2.593-4.194a11.559 11.559 0 0 1 3.824-2.772 11.212 11.212 0 0 1 4.667-.995zm21.781-80.747c2.42 0 4.3.355 5.64 1.066 1.34.71 2.29 1.587 2.852 2.63a6.427 6.427 0 0 1 .778 3.34c-.044 1.185-.195 2.204-.454 3.057-.26.853-.8 2.606-1.62 5.26a589.268 589.268 0 0 1-2.788 8.743 1236.373 1236.373 0 0 0-3.047 9.453c-.994 3.128-1.75 5.592-2.269 7.393-1.123 3.79-2.55 6.42-4.278 7.89-1.728 1.469-3.846 2.203-6.352 2.203H39.023l1.945 12.795h65.342c4.148 0 6.223 1.943 6.223 5.828 0 1.896-.41 3.53-1.232 4.905-.821 1.374-2.442 2.061-4.862 2.061H38.505c-1.729 0-3.176-.426-4.343-1.28-1.167-.852-2.14-1.966-2.917-3.34a21.277 21.277 0 0 1-1.88-4.478 44.128 44.128 0 0 1-1.102-4.55c-.087-.568-.324-1.942-.713-4.122-.39-2.18-.865-4.904-1.426-8.174l-1.88-10.947c-.692-4.027-1.383-8.079-2.075-12.154-1.642-9.572-3.5-20.234-5.574-31.986H6.87c-1.296 0-2.377-.356-3.24-1.067a9.024 9.024 0 0 1-2.14-2.558 10.416 10.416 0 0 1-1.167-3.2C.108 8.53 0 7.488 0 6.54c0-1.896.583-3.46 1.75-4.69C2.917.615 4.494 0 6.482 0h13.095c1.728 0 3.111.284 4.148.853 1.037.569 1.858 1.28 2.463 2.132a8.548 8.548 0 0 1 1.297 2.701c.26.948.475 1.754.648 2.417.173.758.346 1.825.519 3.199.173 1.374.345 2.772.518 4.193.26 1.706.519 3.507.778 5.403h88.678z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/size.svg b/jcdm-ui/src/assets/icons/svg/size.svg
new file mode 100644
index 0000000..ddb25b8
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/size.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M0 54.857h54.796v18.286H36.531V128H18.265V73.143H0V54.857zm127.857-36.571H91.935V128H72.456V18.286H36.534V0h91.326l-.003 18.286z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/skill.svg b/jcdm-ui/src/assets/icons/svg/skill.svg
new file mode 100644
index 0000000..a3b7312
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/skill.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M31.652 93.206h33.401c1.44 2.418 3.077 4.663 4.93 6.692h-38.33v-6.692zm0-10.586h28.914a44.8 44.8 0 0 1-1.264-6.688h-27.65v6.688zm0-17.27H59.39c.288-2.286.714-4.532 1.34-6.687H31.65v6.687h.003zm53.913 44.84v5.85c0 2.798-2.095 5.075-4.667 5.075h-70.07c-2.576 0-4.663-2.277-4.663-5.075V31.26l23.22-20.96v22.25H17.16v6.688h18.39V6.688h45.348c2.576 0 4.667 2.277 4.667 5.066v20.009c1.987-.675 4.053-1.128 6.17-1.445v-18.56C91.738 5.28 86.874 0 80.902 0H31.15L0 28.118v87.917c0 6.48 4.859 11.759 10.832 11.759h70.07c5.974 0 10.837-5.27 10.837-11.759v-4.41c-2.117-.312-4.183-.765-6.17-1.435h-.004zM23.279 58.667h-7.96v6.688h7.96v-6.688zm-7.956 41.23h7.96v-6.691h-7.96v6.692zm7.956-23.96h-7.96v6.687h7.96v-6.688zm89.718-15.042l-4.896-4.07-12.447 17.613-11.19-9.305-3.762 5.311 16.091 13.38 16.204-22.929zM128 70.978c0-18.632-13.97-33.782-31.147-33.782-17.168 0-31.135 15.155-31.135 33.782 0 18.628 13.97 33.783 31.135 33.783 17.172 0 31.143-15.15 31.143-33.783H128zm-6.17 0c0 14.933-11.203 27.1-24.981 27.1-13.77 0-24.987-12.158-24.987-27.1 0-14.941 11.195-27.099 24.987-27.099 13.778 0 24.982 12.158 24.982 27.1z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/slider.svg b/jcdm-ui/src/assets/icons/svg/slider.svg
new file mode 100644
index 0000000..fbe4f39
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/slider.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1577185310368" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1238" xmlns:xlink="http://www.w3.org/1999/xlink" width="81" height="81"><defs><style type="text/css"></style></defs><path d="M951.453125 476.84375H523.671875a131.8359375 131.8359375 0 0 0-254.1796875 0H72.546875v70.3125h196.9453125a131.8359375 131.8359375 0 0 0 254.1796875 0H951.453125z" p-id="1239"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/star.svg b/jcdm-ui/src/assets/icons/svg/star.svg
new file mode 100644
index 0000000..6cf86e6
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/star.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M70.66 4.328l14.01 29.693c1.088 2.29 3.177 3.882 5.603 4.25l31.347 4.76c6.087.926 8.528 8.756 4.117 13.247L103.05 79.395c-1.75 1.78-2.544 4.352-2.132 6.867l5.352 32.641c1.043 6.337-5.33 11.182-10.778 8.19l-28.039-15.409a7.13 7.13 0 0 0-6.91 0l-28.039 15.41c-5.448 2.99-11.821-1.854-10.777-8.19l5.352-32.642c.415-2.515-.387-5.088-2.136-6.867L2.264 56.278C-2.146 51.787.286 43.957 6.38 43.031l31.343-4.76c2.419-.368 4.51-1.96 5.595-4.25L57.334 4.328c2.728-5.77 10.605-5.77 13.325 0z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/swagger.svg b/jcdm-ui/src/assets/icons/svg/swagger.svg
new file mode 100644
index 0000000..05d4e7b
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/swagger.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1566036776944" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6463" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M64 223.995345h168.001164v47.997673c0 26.428509 18.878836 47.997673 41.984 47.997673h140.036654c23.095855 0 41.984-21.569164 41.984-47.997673v-47.997673h504.003491a32.004655 32.004655 0 0 0 0-64.009309H455.996509V111.988364c0-26.428509-18.878836-47.997673-41.984-47.997673H273.985164c-23.095855 0-41.984 21.569164-41.984 47.997673v47.997672H64a32.004655 32.004655 0 0 0 0 64.009309zM288.004655 128h111.997672V256H288.004655V128zM960 479.995345H791.998836v-47.997672c0-26.372655-18.878836-47.997673-41.984-47.997673H609.978182c-23.095855 0-41.984 21.634327-41.984 47.997673v47.997672H64a32.004655 32.004655 0 0 0 0 64.00931h504.003491v47.997672c0 26.363345 18.878836 47.997673 41.984 47.997673h140.036654c23.095855 0 41.984-21.634327 41.984-47.997673v-47.997672h168.001164a32.004655 32.004655 0 1 0-0.009309-64.00931zM735.995345 576H623.997673v-128h111.997672v128zM960 800.293236v-0.288581H455.996509v-47.997673c0-26.363345-18.878836-47.997673-41.984-47.997673H274.050327c-23.105164 0-41.984 21.634327-41.984 47.997673v47.997673H64v0.288581a32.004655 32.004655 0 0 0 0 64.009309c0.986764 0 1.917673-0.195491 2.885818-0.288581h165.115346v47.997672c0 26.363345 18.878836 47.997673 41.984 47.997673h140.036654c23.095855 0 41.984-21.634327 41.984-47.997673v-47.997672h501.108364c0.968145 0.093091 1.899055 0.288582 2.895127 0.288581a32.004655 32.004655 0 1 0-0.009309-64.009309zM400.002327 896H288.004655V768h111.997672v128z" fill="" p-id="6464"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/switch.svg b/jcdm-ui/src/assets/icons/svg/switch.svg
new file mode 100644
index 0000000..0ba61e3
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/switch.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1576042673958" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1110" xmlns:xlink="http://www.w3.org/1999/xlink" width="81" height="81"><defs><style type="text/css"></style></defs><path d="M692 792H332c-150 0-270-120-270-270s120-270 270-270h360c150 0 270 120 270 270 0 147-120 270-270 270zM332 312c-117 0-210 93-210 210s93 210 210 210h360c117 0 210-93 210-210s-93-210-210-210H332z" p-id="1111"></path><path d="M341 522m-150 0a150 150 0 1 0 300 0 150 150 0 1 0-300 0Z" p-id="1112"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/system.svg b/jcdm-ui/src/assets/icons/svg/system.svg
new file mode 100644
index 0000000..5992593
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/system.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1543827724451" class="icon" style="" viewBox="0 0 1084 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10233" xmlns:xlink="http://www.w3.org/1999/xlink" width="211.71875" height="200"><defs><style type="text/css">@font-face { font-family: rbicon; src: url("chrome-extension://dipiagiiohfljcicegpgffpbnjmgjcnf/fonts/rbicon.woff2") format("woff2"); font-weight: normal; font-style: normal; }
+</style></defs><path d="M1080.09609 434.500756c-4.216302-23.731757-26.9241-47.945376-50.595623-53.185637l-17.648235-4.095836a175.940257 175.940257 0 0 1-101.612877-80.832531 177.807476 177.807476 0 0 1-18.732427-129.801867l5.541425-16.684509c7.10748-23.129428-2.108151-54.992624-20.599646-70.833873 0 0-16.624276-14.094495-63.244529-41.199293-46.800951-26.984332-66.858502-34.513443-66.858502-34.513443-22.76803-8.372371-54.631227-0.361397-71.255503 17.407304l-12.287509 13.251234a173.470708 173.470708 0 0 1-120.465769 48.065842A174.13327 174.13327 0 0 1 421.329029 33.590675L409.583617 20.761071C393.140039 2.99237 361.096144-4.898138 338.267881 3.353767c0 0-20.358715 7.529111-67.099434 34.513443-46.800951 27.34573-63.244529 41.440225-63.244529 41.440225-18.431263 15.66055-27.646894 47.222582-20.539413 70.592941l5.059562 16.865207a178.048407 178.048407 0 0 1-18.672194 129.621169 174.916297 174.916297 0 0 1-102.275439 81.073463l-17.045906 3.854904c-23.310126 5.42096-46.258856 29.333415-50.595623 53.185637 0 0-3.854905 21.382674-3.854905 75.712737 0 54.330062 3.854905 75.712736 3.854905 75.712736 4.216302 23.972688 26.9241 47.945376 50.595623 53.185637l16.624276 3.854905a174.253736 174.253736 0 0 1 102.395904 81.314394c23.310126 40.837896 28.911785 87.337683 18.732427 129.801867l-4.81863 16.443578c-7.10748 23.129428 2.108151 54.992624 20.599646 70.833872 0 0 16.624276 14.094495 63.244529 41.199293 46.800951 27.104798 66.918735 34.513443 66.918735 34.513443 22.707798 8.372371 54.631227 0.361397 71.255503-17.407303l11.624947-12.588673a175.096996 175.096996 0 0 1 242.256662 0.120465l11.624947 12.648906c16.383345 17.708468 48.427239 25.598976 71.255503 17.347071 0 0 20.358715-7.529111 67.159666-34.513443 46.740719-27.104798 63.124063-41.199293 63.124064-41.199293 18.491496-15.600317 27.707127-47.463513 20.599646-70.833873l-5.059562-17.106139a176.723284 176.723284 0 0 1 18.672194-129.139305 176.060722 176.060722 0 0 1 102.395904-81.314394l16.68451-3.854905c23.310126-5.42096 46.258856-29.333415 50.595623-53.185637 0 0 3.854905-21.382674 3.854904-75.712737-0.240932-54.330062-4.095836-75.833202-4.095836-75.833202z m-537.819428 293.334149c-119.261112 0-216.175824-97.336342-216.175824-217.621412a216.657687 216.657687 0 0 1 216.236057-217.320249c119.200879 0 216.115591 97.276109 216.11559 217.56118-0.240932 120.044139-96.974945 217.320248-216.175823 217.320249z" p-id="10234"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/tab.svg b/jcdm-ui/src/assets/icons/svg/tab.svg
new file mode 100644
index 0000000..b4b48e4
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/tab.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M78.921.052H49.08c-1.865 0-3.198 1.599-3.198 3.464v6.661c0 1.865 1.6 3.464 3.198 3.464h29.84c1.865 0 3.198-1.599 3.198-3.464V3.516C82.385 1.65 80.786.052 78.92.052zm45.563 0H94.642c-1.865 0-3.464 1.599-3.464 3.464v6.661c0 1.865 1.599 3.464 3.464 3.464h29.842c1.865-.266 3.464-1.599 3.464-3.464V3.516c0-1.865-1.599-3.464-3.464-3.464zm0 22.382H40.02c-1.866 0-3.464-1.599-3.464-3.464V3.516c0-1.865-1.599-3.464-3.464-3.464H3.516C1.65.052.052 1.651.052 3.516V124.75c0 1.598 1.599 3.197 3.464 3.197h120.968c1.865 0 3.464-1.599 3.464-3.464V25.898c0-1.865-1.599-3.464-3.464-3.464z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/table.svg b/jcdm-ui/src/assets/icons/svg/table.svg
new file mode 100644
index 0000000..0e3dc9d
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/table.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M.006.064h127.988v31.104H.006V.064zm0 38.016h38.396v41.472H.006V38.08zm0 48.384h38.396v41.472H.006V86.464zM44.802 38.08h38.396v41.472H44.802V38.08zm0 48.384h38.396v41.472H44.802V86.464zM89.598 38.08h38.396v41.472H89.598zm0 48.384h38.396v41.472H89.598z"/><path d="M.006.064h127.988v31.104H.006V.064zm0 38.016h38.396v41.472H.006V38.08zm0 48.384h38.396v41.472H.006V86.464zM44.802 38.08h38.396v41.472H44.802V38.08zm0 48.384h38.396v41.472H44.802V86.464zM89.598 38.08h38.396v41.472H89.598zm0 48.384h38.396v41.472H89.598z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/textarea.svg b/jcdm-ui/src/assets/icons/svg/textarea.svg
new file mode 100644
index 0000000..2709f29
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/textarea.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1575802855098" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2984" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M896 160H128c-35.2 0-64 28.8-64 64v576c0 35.2 28.8 64 64 64h768c35.2 0 64-28.8 64-64V224c0-35.2-28.8-64-64-64z m0 608c0 16-12.8 32-32 32H160c-19.2 0-32-12.8-32-32V256c0-16 12.8-32 32-32h704c19.2 0 32 12.8 32 32v512z" p-id="2985"></path><path d="M224 288c-19.2 0-32 12.8-32 32v256c0 16 12.8 32 32 32s32-12.8 32-32V320c0-16-12.8-32-32-32z m608 480c19.2 0 32-12.8 32-32V608L704 768h128z" p-id="2986"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/theme.svg b/jcdm-ui/src/assets/icons/svg/theme.svg
new file mode 100644
index 0000000..5982a2f
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/theme.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M125.5 36.984L95.336 2.83C93.735 1.018 91.565 0 89.3 0c-2.263 0-4.433 1.018-6.033 2.83l-3.786 4.286c-1.6 1.812-3.77 2.83-6.032 2.831H54.553c-2.263 0-4.434-1.018-6.033-2.83L44.734 2.83C43.134 1.018 40.964 0 38.701 0c-2.263 0-4.434 1.018-6.034 2.83L2.5 36.984C.9 38.796 0 41.254 0 43.815c0 2.562.899 5.02 2.5 6.831L14.565 64.31c2.178 2.468 5.367 3.403 8.33 2.444 1.35-.435 2.709.592 2.709 2.18v49.407c0 5.313 3.84 9.66 8.532 9.66h59.726c4.693 0 8.532-4.347 8.532-9.66V68.934c0-1.59 1.36-2.616 2.71-2.181 2.962.96 6.15.024 8.329-2.444L125.5 50.646c1.6-1.811 2.499-4.269 2.499-6.83 0-2.563-.899-5.02-2.5-6.832z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/time-range.svg b/jcdm-ui/src/assets/icons/svg/time-range.svg
new file mode 100644
index 0000000..13c1202
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/time-range.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1579774825624" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1248" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M498.595712 482.290351 345.420077 482.290351l0 57.307194 210.477712 0L555.897789 274.196942l-57.301054 0L498.596735 482.290351zM498.595712 482.290351" p-id="1249"></path><path d="M577.685002 644.98478l379.879913 0 0 57.302077L577.685002 702.286858 577.685002 644.98478 577.685002 644.98478zM577.685002 644.98478" p-id="1250"></path><path d="M577.685002 773.764795l379.879913 0 0 57.307194L577.685002 831.071989 577.685002 773.764795 577.685002 773.764795zM577.685002 773.764795" p-id="1251"></path><path d="M577.685002 902.549927l379.879913 0 0 57.307194L577.685002 959.857121 577.685002 902.549927 577.685002 902.549927zM577.685002 902.549927" p-id="1252"></path><path d="M102.523001 382.290823c4.450359 2.615571 9.470699 3.954055 14.530948 3.954055 2.969635 0 5.952572-0.461511 8.836249-1.394766l190.809767-61.886489c15.052834-4.882194 23.297612-21.040199 18.415418-36.08894-4.882194-15.052834-21.040199-23.297612-36.093033-18.415418L175.676092 308.458257c15.994276-26.115797 35.170011-50.537 57.370639-72.743768 73.767074-73.767074 171.845857-114.388237 276.16783-114.388237 104.32095 0 202.39564 40.622186 276.16169 114.388237s114.393353 171.845857 114.393353 276.16783c0 26.427906-2.615571 52.449559-7.709589 77.780481l58.302871 0c4.464685-25.499767 6.708795-51.470255 6.708795-77.780481 0-60.449767-11.845793-119.102608-35.204803-174.336584-22.559808-53.334719-54.850236-101.226472-95.968725-142.349055-41.122583-41.122583-89.017406-73.408917-142.348032-95.968725C628.317169 75.866898 569.659211 64.021106 509.215584 64.021106c-60.448744 0-119.106702 11.845793-174.336584 35.207873-53.334719 22.559808-101.230566 54.846142-142.349055 95.968725-23.980157 23.980157-44.934398 50.278103-62.727647 78.601172l-20.738323-105.655342c-3.043313-15.527648-18.105357-25.642007-33.631982-22.599717-15.527648 3.048429-25.64303 18.105357-22.599717 33.637098l36.102243 183.932126C90.51348 371.153158 95.460142 378.13313 102.523001 382.290823L102.523001 382.290823zM102.523001 382.290823" p-id="1253"></path><path d="M126.020158 587.9416 67.768453 587.9416c5.759167 33.679054 15.368012 66.544579 28.789697 98.278327 22.559808 53.333696 54.850236 101.225449 95.971795 142.348032 41.122583 41.122583 89.014336 73.408917 142.349055 95.968725 54.112432 22.88829 111.517863 34.71157 170.668031 35.18229L505.547031 902.395408c-102.94972-0.941442-199.594851-41.445948-272.499277-114.349351C177.545672 732.543975 140.810003 663.275355 126.020158 587.9416L126.020158 587.9416zM126.020158 587.9416" p-id="1254"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/time.svg b/jcdm-ui/src/assets/icons/svg/time.svg
new file mode 100644
index 0000000..b376e32
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/time.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1577099827399" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1008" xmlns:xlink="http://www.w3.org/1999/xlink" width="81" height="81"><defs><style type="text/css"></style></defs><path d="M520 559h204c17.673 0 32 14.327 32 32 0 17.673-14.327 32-32 32H488c-17.673 0-32-14.327-32-32 0-0.167 0.001-0.334 0.004-0.5a32.65 32.65 0 0 1-0.004-0.5V277c0-17.673 14.327-32 32-32 17.673 0 32 14.327 32 32v282z m-8 401C264.576 960 64 759.424 64 512S264.576 64 512 64s448 200.576 448 448-200.576 448-448 448z m0-64c212.077 0 384-171.923 384-384S724.077 128 512 128 128 299.923 128 512s171.923 384 384 384z" p-id="1009"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/tool.svg b/jcdm-ui/src/assets/icons/svg/tool.svg
new file mode 100644
index 0000000..48e0e35
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/tool.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1553828490559" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1684" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M898.831744 900.517641 103.816972 900.517641c-36.002982 0-65.363683-29.286-65.363683-65.313541l0-554.949184c0-36.041868 29.361725-65.326844 65.363683-65.326844l795.015795 0c36.002982 0 65.198931 29.284977 65.198931 65.326844l0 554.949184C964.030675 871.231641 934.834726 900.517641 898.831744 900.517641L898.831744 900.517641zM103.816972 255.593236c-13.576203 0-24.711821 11.085476-24.711821 24.662703l0 554.949184c0 13.576203 11.136641 24.662703 24.711821 24.662703l795.015795 0c13.577227 0 24.547069-11.086499 24.547069-24.662703l0-554.949184c0-13.577227-10.970866-24.662703-24.547069-24.662703L103.816972 255.593236 103.816972 255.593236zM664.346245 251.774257c-11.161201 0-20.332071-9.080819-20.332071-20.332071l0-101.278661c0-13.576203-11.047614-24.623817-24.699542-24.623817L383.181611 105.539708c-13.576203 0-24.712845 11.04659-24.712845 24.623817l0 101.278661c0 11.252275-9.041934 20.332071-20.332071 20.332071-11.20111 0-20.319791-9.080819-20.319791-20.332071l0-101.278661c0-35.989679 29.323862-65.275679 65.364707-65.275679l236.133022 0c36.06745 0 65.402569 29.284977 65.402569 65.275679l0 101.278661C684.717202 242.694461 675.636383 251.774257 664.346245 251.774257L664.346245 251.774257zM413.233044 521.725502 75.694471 521.725502c-11.163247 0-20.333094-9.117658-20.333094-20.35663 0-11.252275 9.169847-20.332071 20.333094-20.332071l337.538573 0c11.277858 0 20.319791 9.080819 20.319791 20.332071C433.552835 512.607844 424.510902 521.725502 413.233044 521.725502L413.233044 521.725502zM912.894018 521.725502 575.367725 521.725502c-11.213389 0-20.332071-9.117658-20.332071-20.35663 0-11.252275 9.118682-20.332071 20.332071-20.332071l337.526293 0c11.290137 0 20.332071 9.080819 20.332071 20.332071C933.226089 512.607844 924.184155 521.725502 912.894018 521.725502L912.894018 521.725502zM557.56322 634.217552 445.085496 634.217552c-11.213389 0-20.332071-9.079796-20.332071-20.331048l0-168.763658c0-11.251252 9.118682-20.332071 20.332071-20.332071l112.478747 0c11.290137 0 20.370956 9.080819 20.370956 20.332071l0 168.763658C577.934177 625.137757 568.853357 634.217552 557.56322 634.217552L557.56322 634.217552zM465.417567 593.514525l71.827909 0L537.245476 465.454918l-71.827909 0L465.417567 593.514525 465.417567 593.514525z" p-id="1685"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/tree-table.svg b/jcdm-ui/src/assets/icons/svg/tree-table.svg
new file mode 100644
index 0000000..8aafdb8
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/tree-table.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M44.8 0h79.543C126.78 0 128 1.422 128 4.267v23.466c0 2.845-1.219 4.267-3.657 4.267H44.8c-2.438 0-3.657-1.422-3.657-4.267V4.267C41.143 1.422 42.362 0 44.8 0zm22.857 48h56.686c2.438 0 3.657 1.422 3.657 4.267v23.466c0 2.845-1.219 4.267-3.657 4.267H67.657C65.22 80 64 78.578 64 75.733V52.267C64 49.422 65.219 48 67.657 48zm0 48h56.686c2.438 0 3.657 1.422 3.657 4.267v23.466c0 2.845-1.219 4.267-3.657 4.267H67.657C65.22 128 64 126.578 64 123.733v-23.466C64 97.422 65.219 96 67.657 96zM50.286 68.267c2.02 0 3.657-1.91 3.657-4.267 0-2.356-1.638-4.267-3.657-4.267H17.37V32h6.4c2.02 0 3.658-1.91 3.658-4.267V4.267C27.429 1.91 25.79 0 23.77 0H3.657C1.637 0 0 1.91 0 4.267v23.466C0 30.09 1.637 32 3.657 32h6.4v80c0 2.356 1.638 4.267 3.657 4.267h36.572c2.02 0 3.657-1.91 3.657-4.267 0-2.356-1.638-4.267-3.657-4.267H17.37V68.267h32.915z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/tree.svg b/jcdm-ui/src/assets/icons/svg/tree.svg
new file mode 100644
index 0000000..dd4b7dd
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/tree.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M126.713 90.023c.858.985 1.287 2.134 1.287 3.447v29.553c0 1.423-.429 2.6-1.287 3.53-.858.93-1.907 1.395-3.146 1.395H97.824c-1.145 0-2.146-.465-3.004-1.395-.858-.93-1.287-2.107-1.287-3.53V93.47c0-.875.19-1.696.572-2.462.382-.766.906-1.368 1.573-1.806a3.84 3.84 0 0 1 2.146-.657h9.725V69.007a3.84 3.84 0 0 0-.43-1.806 3.569 3.569 0 0 0-1.143-1.313 2.714 2.714 0 0 0-1.573-.492h-36.47v23.149h9.725c1.144 0 2.145.492 3.004 1.478.858.985 1.287 2.134 1.287 3.447v29.553c0 .876-.191 1.696-.573 2.463-.38.766-.905 1.368-1.573 1.806a3.84 3.84 0 0 1-2.145.656H51.915a3.84 3.84 0 0 1-2.145-.656c-.668-.438-1.216-1.04-1.645-1.806a4.96 4.96 0 0 1-.644-2.463V93.47c0-1.313.43-2.462 1.288-3.447.858-.986 1.907-1.478 3.146-1.478h9.582v-23.15h-37.9c-.953 0-1.74.356-2.359 1.068-.62.711-.93 1.56-.93 2.544v19.538h9.726c1.239 0 2.264.492 3.074 1.478.81.985 1.216 2.134 1.216 3.447v29.553c0 1.423-.405 2.6-1.216 3.53-.81.93-1.835 1.395-3.074 1.395H4.29c-.476 0-.93-.082-1.358-.246a4.1 4.1 0 0 1-1.144-.657 4.658 4.658 0 0 1-.93-1.067 5.186 5.186 0 0 1-.643-1.395 5.566 5.566 0 0 1-.215-1.56V93.47c0-.437.048-.875.143-1.313a3.95 3.95 0 0 1 .429-1.15c.19-.328.429-.656.715-.984.286-.329.572-.602.858-.821.286-.22.62-.383 1.001-.493.382-.11.763-.164 1.144-.164h9.726V61.619c0-.985.31-1.833.93-2.544.619-.712 1.358-1.068 2.216-1.068h44.335V39.62h-9.582c-1.24 0-2.288-.492-3.146-1.477a5.09 5.09 0 0 1-1.287-3.448V5.14c0-1.423.429-2.627 1.287-3.612.858-.985 1.907-1.477 3.146-1.477h25.743c.763 0 1.478.246 2.145.739a5.17 5.17 0 0 1 1.573 1.888c.382.766.573 1.587.573 2.462v29.553c0 1.313-.43 2.463-1.287 3.448-.859.985-1.86 1.477-3.004 1.477h-9.725v18.389h42.762c.954 0 1.74.355 2.36 1.067.62.711.93 1.56.93 2.545v26.925h9.582c1.239 0 2.288.492 3.146 1.478z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/upload.svg b/jcdm-ui/src/assets/icons/svg/upload.svg
new file mode 100644
index 0000000..bae49c0
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/upload.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1577540289643" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7922" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M530.944 458.24l4.8 3.456 122.176 106.816a32 32 0 0 1-37.44 51.584l-4.672-3.392L546.56 556.16v280.704a32 32 0 0 1-26.24 31.488l-5.76 0.512a32 32 0 0 1-31.424-26.24l-0.512-5.76-0.064-280.704-69.12 60.48a32 32 0 0 1-40.96 0.896l-4.16-3.968a32 32 0 0 1-0.96-40.96l4.032-4.16 122.176-106.816a32 32 0 0 1 37.312-3.456zM497.92 128c128.128 0 239.168 82.304 275.52 199.04 123.968 11.264 221.312 113.088 221.312 237.44 0 128.128-103.68 232.96-234.88 238.272h-5.888l-35.52 0.192a32 32 0 0 1-0.192-64l35.264-0.128 4.672-0.064c96.384-3.84 172.544-80.896 172.544-174.272 0-96.128-80.512-174.464-179.584-174.464h-1.984a32 32 0 0 1-32-25.28C695.872 264.96 604.736 192 497.92 192 381.824 192 285.44 277.76 274.816 388.48a32 32 0 0 1-28.352 28.8c-83.968 9.152-147.84 78.208-147.84 159.552l0.192 7.936c3.84 85.76 77.056 154.112 166.592 154.112h45.632a32 32 0 0 1 0 64h-45.632C142.016 802.944 40.32 708.032 34.88 586.88l-0.192-9.28c0-106.88 76.352-197.184 179.968-219.904C239.488 226.112 357.76 128 497.856 128z" p-id="7923"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/user.svg b/jcdm-ui/src/assets/icons/svg/user.svg
new file mode 100644
index 0000000..0ba0716
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/user.svg
@@ -0,0 +1 @@
+<svg width="130" height="130" xmlns="http://www.w3.org/2000/svg"><path d="M63.444 64.996c20.633 0 37.359-14.308 37.359-31.953 0-17.649-16.726-31.952-37.359-31.952-20.631 0-37.36 14.303-37.358 31.952 0 17.645 16.727 31.953 37.359 31.953zM80.57 75.65H49.434c-26.652 0-48.26 18.477-48.26 41.27v2.664c0 9.316 21.608 9.325 48.26 9.325H80.57c26.649 0 48.256-.344 48.256-9.325v-2.663c0-22.794-21.605-41.271-48.256-41.271z" stroke="#979797"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/validCode.svg b/jcdm-ui/src/assets/icons/svg/validCode.svg
new file mode 100644
index 0000000..cfb1021
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/validCode.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1569580729849" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1939" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M513.3 958.5c-142.2 0-397.9-222.1-401.6-440.5V268c1.7-39.6 31.7-72.3 71.1-77.3 49-4.6 97.1-16.5 142.7-35.3 47.8-14 91.9-38.3 129.4-71.1 30.3-24.4 72.9-26.3 105.3-4.6 39.9 30.7 83.8 55.9 130.5 74.6 48.6 14.7 98.2 25.9 148.4 33.7 38.5 7.6 67.1 40.3 69.5 79.5 3.3 84.9 2.5 169.9-2.6 254.7-33.7 281.6-253.7 436.4-392.7 436.3z m-0.1-813.7c-7.2-0.2-14.3 2-20 6.4-39.7 35.2-86.8 61.1-137.7 75.7-46.8 19.2-96.2 31-146.6 35.2-11 3.2-18.8 13-19.5 24.4v230.1c3.5 180.3 223.3 361 323.9 361s287.3-120.2 317.6-360.5c7.3-142.7 0-228.6 0-229.6-1.3-13.3-11-24.3-24-27.3-49.6-7.7-98.6-19-146.5-33.7-46.3-19.5-89.7-45.3-129-76.7-5.8-3.8-12.7-5.5-19.5-4.9l1.3-0.1z" fill="#C6CCDA" p-id="1940"></path><path d="M750.1 428L490.7 673.2c-11.7 11.1-29.5 12.9-43.1 4.2l-6.8-5.8-141.2-149.4c-9.3-9.3-12.7-22.9-9-35.5 3.8-12.6 14.1-22.1 27-24.8 12.9-2.7 26.1 1.9 34.6 11.9L469 597.5l233.7-221c14.6-12.8 36.8-11.6 49.9 2.7 13.2 14.2 11.5 35.3-2.5 48.8" fill="#C6CCDA" p-id="1941"></path></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/wechat.svg b/jcdm-ui/src/assets/icons/svg/wechat.svg
new file mode 100644
index 0000000..c586e55
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/wechat.svg
@@ -0,0 +1 @@
+<svg width="128" height="110" xmlns="http://www.w3.org/2000/svg"><path d="M86.635 33.334c1.467 0 2.917.113 4.358.283C87.078 14.392 67.58.111 45.321.111 20.44.111.055 17.987.055 40.687c0 13.104 6.781 23.863 18.115 32.209l-4.527 14.352 15.82-8.364c5.666 1.182 10.207 2.395 15.858 2.395 1.42 0 2.829-.073 4.227-.189-.886-3.19-1.398-6.53-1.398-9.996 0-20.845 16.98-37.76 38.485-37.76zm-24.34-12.936c3.407 0 5.665 2.363 5.665 5.954 0 3.576-2.258 5.97-5.666 5.97-3.392 0-6.795-2.395-6.795-5.97 0-3.591 3.403-5.954 6.795-5.954zM30.616 32.323c-3.393 0-6.818-2.395-6.818-5.971 0-3.591 3.425-5.954 6.818-5.954 3.392 0 5.65 2.363 5.65 5.954 0 3.576-2.258 5.97-5.65 5.97z"/><path d="M127.945 70.52c0-19.075-18.108-34.623-38.448-34.623-21.537 0-38.5 15.548-38.5 34.623 0 19.108 16.963 34.622 38.5 34.622 4.508 0 9.058-1.2 13.584-2.395l12.414 7.167-3.404-11.923c9.087-7.184 15.854-16.712 15.854-27.471zm-50.928-5.97c-2.254 0-4.53-2.362-4.53-4.773 0-2.378 2.276-4.771 4.53-4.771 3.422 0 5.665 2.393 5.665 4.771 0 2.41-2.243 4.773-5.665 4.773zm24.897 0c-2.24 0-4.498-2.362-4.498-4.773 0-2.378 2.258-4.771 4.498-4.771 3.392 0 5.665 2.393 5.665 4.771 0 2.41-2.273 4.773-5.665 4.773z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svg/zip.svg b/jcdm-ui/src/assets/icons/svg/zip.svg
new file mode 100644
index 0000000..f806fc4
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svg/zip.svg
@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M78.527 116.793c.178.008.348.024.527.024h40.233c4.711-.005 8.53-3.677 8.534-8.21V18.895c-.004-4.532-3.823-8.204-8.534-8.209H79.054c-.179 0-.353.016-.527.024V0L0 10.082v107.406l78.527 10.342v-11.037zm0-101.362c.174-.024.348-.052.527-.052h40.233c2.018 0 3.659 1.578 3.659 3.52v89.713c-.003 1.942-1.64 3.517-3.659 3.519H79.054c-.179 0-.353-.028-.527-.052V15.431zM30.262 75.757l-18.721-.46V72.37l11.3-16.673v-.148l-10.266.164v-4.51l17.504-.44v3.264L18.696 70.76v.144l11.566.176v4.678zm9.419.231l-5.823-.144V50.671l5.823-.144v25.461zm22.255-11.632c-2.168 1.922-5.353 2.76-9.02 2.736-.702.004-1.402-.04-2.097-.131v9.303l-5.997-.148V50.743c1.852-.352 4.473-.647 8.218-.743 3.838-.096 6.608.539 8.48 1.913 1.807 1.306 3.032 3.5 3.032 6.112s-.926 4.833-2.612 6.331h-.004zM53.36 54.45c-.856-.01-1.71.083-2.541.275v7.682c.523.116 1.167.152 2.06.152 3.301-.004 5.36-1.614 5.36-4.314 0-2.425-1.772-3.843-4.875-3.791l-.004-.004zm39.847-37.066h9.564v3.795h-9.564v-3.795zm-9.568 5.68h9.564v3.8h-9.564v-3.8zm9.568 6.216h9.564v3.799h-9.564V29.28zm0 12h9.564v3.794h-9.564V41.28zm-9.568-6.096h9.564v3.795h-9.564v-3.795zm9.472 47.064c2.512 0 4.921-.96 6.697-2.67 1.776-1.708 2.773-4.026 2.772-6.442l-1.748-15.263c0-5.033-2.492-9.112-7.725-9.112-5.232 0-7.72 4.079-7.72 9.112l-1.752 15.263c-.001 2.417.996 4.735 2.773 6.444 1.777 1.71 4.187 2.669 6.7 2.668h.003zm-3.135-16.75h6.27v12.743h-6.27V65.5z"/></svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/icons/svgo.yml b/jcdm-ui/src/assets/icons/svgo.yml
new file mode 100644
index 0000000..d11906a
--- /dev/null
+++ b/jcdm-ui/src/assets/icons/svgo.yml
@@ -0,0 +1,22 @@
+# replace default config
+
+# multipass: true
+# full: true
+
+plugins:
+
+  # - name
+  #
+  # or:
+  # - name: false
+  # - name: true
+  #
+  # or:
+  # - name:
+  #     param1: 1
+  #     param2: 2
+
+- removeAttrs:
+    attrs:
+      - 'fill'
+      - 'fill-rule'
diff --git a/jcdm-ui/src/assets/images/dark.svg b/jcdm-ui/src/assets/images/dark.svg
new file mode 100644
index 0000000..f646bd7
--- /dev/null
+++ b/jcdm-ui/src/assets/images/dark.svg
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="52px" height="45px" viewBox="0 0 52 45" version="1.1" 
+    xmlns="http://www.w3.org/2000/svg" 
+    xmlns:xlink="http://www.w3.org/1999/xlink">
+    <defs>
+        <filter x="-9.4%" y="-6.2%" width="118.8%" height="122.5%" filterUnits="objectBoundingBox" id="filter-1">
+            <feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
+            <feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
+            <feColorMatrix values="0 0 0 0 0   0 0 0 0 0   0 0 0 0 0  0 0 0 0.15 0" type="matrix" in="shadowBlurOuter1" result="shadowMatrixOuter1"></feColorMatrix>
+            <feMerge>
+                <feMergeNode in="shadowMatrixOuter1"></feMergeNode>
+                <feMergeNode in="SourceGraphic"></feMergeNode>
+            </feMerge>
+        </filter>
+        <rect id="path-2" x="0" y="0" width="48" height="40" rx="4"></rect>
+        <filter x="-4.2%" y="-2.5%" width="108.3%" height="110.0%" filterUnits="objectBoundingBox" id="filter-4">
+            <feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
+            <feGaussianBlur stdDeviation="0.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
+            <feColorMatrix values="0 0 0 0 0   0 0 0 0 0   0 0 0 0 0  0 0 0 0.1 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
+        </filter>
+    </defs>
+    <g id="閰嶇疆闈㈡澘" width="48" height="40" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="setting-copy-2" width="48" height="40" transform="translate(-1190.000000, -136.000000)">
+            <g id="Group-8" width="48" height="40" transform="translate(1167.000000, 0.000000)">
+                <g id="Group-5-Copy-5" filter="url(#filter-1)" transform="translate(25.000000, 137.000000)">
+                    <mask id="mask-3" fill="white">
+                        <use xlink:href="#path-2"></use>
+                    </mask>
+                    <g id="Rectangle-18">
+                        <use fill="black" fill-opacity="1" filter="url(#filter-4)" xlink:href="#path-2"></use>
+                        <use fill="#F0F2F5" fill-rule="evenodd" xlink:href="#path-2"></use>
+                    </g>
+                    <rect id="Rectangle-11" fill="#FFFFFF" mask="url(#mask-3)" x="0" y="0" width="48" height="10"></rect>
+                    <rect id="Rectangle-18" fill="#303648" mask="url(#mask-3)" x="0" y="0" width="16" height="40"></rect>
+                </g>
+            </g>
+        </g>
+    </g>
+</svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/images/light.svg b/jcdm-ui/src/assets/images/light.svg
new file mode 100644
index 0000000..ab7cc08
--- /dev/null
+++ b/jcdm-ui/src/assets/images/light.svg
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="52px" height="45px" viewBox="0 0 52 45" version="1.1" 
+    xmlns="http://www.w3.org/2000/svg" 
+    xmlns:xlink="http://www.w3.org/1999/xlink">
+    <defs>
+        <filter x="-9.4%" y="-6.2%" width="118.8%" height="122.5%" filterUnits="objectBoundingBox" id="filter-1">
+            <feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
+            <feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
+            <feColorMatrix values="0 0 0 0 0   0 0 0 0 0   0 0 0 0 0  0 0 0 0.15 0" type="matrix" in="shadowBlurOuter1" result="shadowMatrixOuter1"></feColorMatrix>
+            <feMerge>
+                <feMergeNode in="shadowMatrixOuter1"></feMergeNode>
+                <feMergeNode in="SourceGraphic"></feMergeNode>
+            </feMerge>
+        </filter>
+        <rect id="path-2" x="0" y="0" width="48" height="40" rx="4"></rect>
+        <filter x="-4.2%" y="-2.5%" width="108.3%" height="110.0%" filterUnits="objectBoundingBox" id="filter-4">
+            <feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
+            <feGaussianBlur stdDeviation="0.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
+            <feColorMatrix values="0 0 0 0 0   0 0 0 0 0   0 0 0 0 0  0 0 0 0.1 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
+        </filter>
+    </defs>
+    <g id="閰嶇疆闈㈡澘" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="setting-copy-2" transform="translate(-1254.000000, -136.000000)">
+            <g id="Group-8" transform="translate(1167.000000, 0.000000)">
+                <g id="Group-5" filter="url(#filter-1)" transform="translate(89.000000, 137.000000)">
+                    <mask id="mask-3" fill="white">
+                        <use xlink:href="#path-2"></use>
+                    </mask>
+                    <g id="Rectangle-18">
+                        <use fill="black" fill-opacity="1" filter="url(#filter-4)" xlink:href="#path-2"></use>
+                        <use fill="#F0F2F5" fill-rule="evenodd" xlink:href="#path-2"></use>
+                    </g>
+                    <rect id="Rectangle-18" fill="#FFFFFF" mask="url(#mask-3)" x="0" y="0" width="16" height="40"></rect>
+                    <rect id="Rectangle-11" fill="#FFFFFF" mask="url(#mask-3)" x="0" y="0" width="48" height="10"></rect>
+                </g>
+            </g>
+        </g>
+    </g>
+</svg>
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/images/login-background.jpg b/jcdm-ui/src/assets/images/login-background.jpg
new file mode 100644
index 0000000..8a89eb8
--- /dev/null
+++ b/jcdm-ui/src/assets/images/login-background.jpg
Binary files differ
diff --git a/jcdm-ui/src/assets/images/login-background.png b/jcdm-ui/src/assets/images/login-background.png
new file mode 100644
index 0000000..384dd6c
--- /dev/null
+++ b/jcdm-ui/src/assets/images/login-background.png
Binary files differ
diff --git a/jcdm-ui/src/assets/images/login-background1.png b/jcdm-ui/src/assets/images/login-background1.png
new file mode 100644
index 0000000..aef2da8
--- /dev/null
+++ b/jcdm-ui/src/assets/images/login-background1.png
Binary files differ
diff --git a/jcdm-ui/src/assets/images/pay.png b/jcdm-ui/src/assets/images/pay.png
new file mode 100644
index 0000000..354ed31
--- /dev/null
+++ b/jcdm-ui/src/assets/images/pay.png
Binary files differ
diff --git a/jcdm-ui/src/assets/images/profile.jpg b/jcdm-ui/src/assets/images/profile.jpg
new file mode 100644
index 0000000..b3a940b
--- /dev/null
+++ b/jcdm-ui/src/assets/images/profile.jpg
Binary files differ
diff --git a/jcdm-ui/src/assets/logo/logo.png b/jcdm-ui/src/assets/logo/logo.png
new file mode 100644
index 0000000..5d0a47f
--- /dev/null
+++ b/jcdm-ui/src/assets/logo/logo.png
Binary files differ
diff --git a/jcdm-ui/src/assets/styles/btn.scss b/jcdm-ui/src/assets/styles/btn.scss
new file mode 100644
index 0000000..e6ba1a8
--- /dev/null
+++ b/jcdm-ui/src/assets/styles/btn.scss
@@ -0,0 +1,99 @@
+@import './variables.scss';
+
+@mixin colorBtn($color) {
+  background: $color;
+
+  &:hover {
+    color: $color;
+
+    &:before,
+    &:after {
+      background: $color;
+    }
+  }
+}
+
+.blue-btn {
+  @include colorBtn($blue)
+}
+
+.light-blue-btn {
+  @include colorBtn($light-blue)
+}
+
+.red-btn {
+  @include colorBtn($red)
+}
+
+.pink-btn {
+  @include colorBtn($pink)
+}
+
+.green-btn {
+  @include colorBtn($green)
+}
+
+.tiffany-btn {
+  @include colorBtn($tiffany)
+}
+
+.yellow-btn {
+  @include colorBtn($yellow)
+}
+
+.pan-btn {
+  font-size: 14px;
+  color: #fff;
+  padding: 14px 36px;
+  border-radius: 8px;
+  border: none;
+  outline: none;
+  transition: 600ms ease all;
+  position: relative;
+  display: inline-block;
+
+  &:hover {
+    background: #fff;
+
+    &:before,
+    &:after {
+      width: 100%;
+      transition: 600ms ease all;
+    }
+  }
+
+  &:before,
+  &:after {
+    content: '';
+    position: absolute;
+    top: 0;
+    right: 0;
+    height: 2px;
+    width: 0;
+    transition: 400ms ease all;
+  }
+
+  &::after {
+    right: inherit;
+    top: inherit;
+    left: 0;
+    bottom: 0;
+  }
+}
+
+.custom-button {
+  display: inline-block;
+  line-height: 1;
+  white-space: nowrap;
+  cursor: pointer;
+  background: #fff;
+  color: #fff;
+  -webkit-appearance: none;
+  text-align: center;
+  box-sizing: border-box;
+  outline: 0;
+  margin: 0;
+  padding: 10px 15px;
+  font-size: 14px;
+  border-radius: 4px;
+}
diff --git a/jcdm-ui/src/assets/styles/element-ui.scss b/jcdm-ui/src/assets/styles/element-ui.scss
new file mode 100644
index 0000000..363092a
--- /dev/null
+++ b/jcdm-ui/src/assets/styles/element-ui.scss
@@ -0,0 +1,92 @@
+// cover some element-ui styles
+
+.el-breadcrumb__inner,
+.el-breadcrumb__inner a {
+  font-weight: 400 !important;
+}
+
+.el-upload {
+  input[type="file"] {
+    display: none !important;
+  }
+}
+
+.el-upload__input {
+  display: none;
+}
+
+.cell {
+  .el-tag {
+    margin-right: 0px;
+  }
+}
+
+.small-padding {
+  .cell {
+    padding-left: 5px;
+    padding-right: 5px;
+  }
+}
+
+.fixed-width {
+  .el-button--mini {
+    padding: 7px 10px;
+    width: 60px;
+  }
+}
+
+.status-col {
+  .cell {
+    padding: 0 10px;
+    text-align: center;
+
+    .el-tag {
+      margin-right: 0px;
+    }
+  }
+}
+
+// to fixed https://github.com/ElemeFE/element/issues/2461
+.el-dialog {
+  transform: none;
+  left: 0;
+  position: relative;
+  margin: 0 auto;
+}
+
+// refine element ui upload
+.upload-container {
+  .el-upload {
+    width: 100%;
+
+    .el-upload-dragger {
+      width: 100%;
+      height: 200px;
+    }
+  }
+}
+
+// dropdown
+.el-dropdown-menu {
+  a {
+    display: block
+  }
+}
+
+// fix date-picker ui bug in filter-item
+.el-range-editor.el-input__inner {
+  display: inline-flex !important;
+}
+
+// to fix el-date-picker css style
+.el-range-separator {
+  box-sizing: content-box;
+}
+
+.el-menu--collapse
+  > div
+  > .el-submenu
+  > .el-submenu__title
+  .el-submenu__icon-arrow {
+  display: none;
+}
\ No newline at end of file
diff --git a/jcdm-ui/src/assets/styles/element-variables.scss b/jcdm-ui/src/assets/styles/element-variables.scss
new file mode 100644
index 0000000..1615ff2
--- /dev/null
+++ b/jcdm-ui/src/assets/styles/element-variables.scss
@@ -0,0 +1,31 @@
+/**
+* I think element-ui's default theme color is too light for long-term use.
+* So I modified the default color and you can modify it to your liking.
+**/
+
+/* theme color */
+$--color-primary: #1890ff;
+$--color-success: #13ce66;
+$--color-warning: #ffba00;
+$--color-danger: #ff4949;
+// $--color-info: #1E1E1E;
+
+$--button-font-weight: 400;
+
+// $--color-text-regular: #1f2d3d;
+
+$--border-color-light: #dfe4ed;
+$--border-color-lighter: #e6ebf5;
+
+$--table-border: 1px solid #dfe6ec;
+
+/* icon font path, required */
+$--font-path: '~element-ui/lib/theme-chalk/fonts';
+
+@import "~element-ui/packages/theme-chalk/src/index";
+
+// the :export directive is the magic sauce for webpack
+// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
+:export {
+  theme: $--color-primary;
+}
diff --git a/jcdm-ui/src/assets/styles/index.scss b/jcdm-ui/src/assets/styles/index.scss
new file mode 100644
index 0000000..cbbbe52
--- /dev/null
+++ b/jcdm-ui/src/assets/styles/index.scss
@@ -0,0 +1,186 @@
+@import './variables.scss';
+@import './mixin.scss';
+@import './transition.scss';
+@import './element-ui.scss';
+@import './sidebar.scss';
+@import './btn.scss';
+
+body {
+  height: 100%;
+  -moz-osx-font-smoothing: grayscale;
+  -webkit-font-smoothing: antialiased;
+  text-rendering: optimizeLegibility;
+  font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
+}
+
+label {
+  font-weight: 700;
+}
+
+html {
+  height: 100%;
+  box-sizing: border-box;
+}
+
+#app {
+  height: 100%;
+}
+
+*,
+*:before,
+*:after {
+  box-sizing: inherit;
+}
+
+.no-padding {
+  padding: 0px !important;
+}
+
+.padding-content {
+  padding: 4px 0;
+}
+
+a:focus,
+a:active {
+  outline: none;
+}
+
+a,
+a:focus,
+a:hover {
+  cursor: pointer;
+  color: inherit;
+  text-decoration: none;
+}
+
+div:focus {
+  outline: none;
+}
+
+.fr {
+  float: right;
+}
+
+.fl {
+  float: left;
+}
+
+.pr-5 {
+  padding-right: 5px;
+}
+
+.pl-5 {
+  padding-left: 5px;
+}
+
+.block {
+  display: block;
+}
+
+.pointer {
+  cursor: pointer;
+}
+
+.inlineBlock {
+  display: block;
+}
+
+.clearfix {
+  &:after {
+    visibility: hidden;
+    display: block;
+    font-size: 0;
+    content: " ";
+    clear: both;
+    height: 0;
+  }
+}
+
+aside {
+  background: #eef1f6;
+  padding: 8px 24px;
+  margin-bottom: 20px;
+  border-radius: 2px;
+  display: block;
+  line-height: 32px;
+  font-size: 16px;
+  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
+  color: #2c3e50;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+
+  a {
+    color: #337ab7;
+    cursor: pointer;
+
+    &:hover {
+      color: rgb(32, 160, 255);
+    }
+  }
+}
+
+//main-container鍏ㄥ眬鏍峰紡
+.app-container {
+  padding: 20px;
+}
+
+.components-container {
+  margin: 30px 50px;
+  position: relative;
+}
+
+.pagination-container {
+  margin-top: 30px;
+}
+
+.text-center {
+  text-align: center
+}
+
+.sub-navbar {
+  height: 50px;
+  line-height: 50px;
+  position: relative;
+  width: 100%;
+  text-align: right;
+  padding-right: 20px;
+  transition: 600ms ease position;
+  background: linear-gradient(90deg, rgba(32, 182, 249, 1) 0%, rgba(32, 182, 249, 1) 0%, rgba(33, 120, 241, 1) 100%, rgba(33, 120, 241, 1) 100%);
+
+  .subtitle {
+    font-size: 20px;
+    color: #fff;
+  }
+
+  &.draft {
+    background: #d0d0d0;
+  }
+
+  &.deleted {
+    background: #d0d0d0;
+  }
+}
+
+.link-type,
+.link-type:focus {
+  color: #337ab7;
+  cursor: pointer;
+
+  &:hover {
+    color: rgb(32, 160, 255);
+  }
+}
+
+.filter-container {
+  padding-bottom: 10px;
+
+  .filter-item {
+    display: inline-block;
+    vertical-align: middle;
+    margin-bottom: 10px;
+  }
+}
+
+.el-dialog__header{
+  background-color: #f8f8f9;
+}
diff --git a/jcdm-ui/src/assets/styles/mixin.scss b/jcdm-ui/src/assets/styles/mixin.scss
new file mode 100644
index 0000000..06fa061
--- /dev/null
+++ b/jcdm-ui/src/assets/styles/mixin.scss
@@ -0,0 +1,66 @@
+@mixin clearfix {
+  &:after {
+    content: "";
+    display: table;
+    clear: both;
+  }
+}
+
+@mixin scrollBar {
+  &::-webkit-scrollbar-track-piece {
+    background: #d3dce6;
+  }
+
+  &::-webkit-scrollbar {
+    width: 6px;
+  }
+
+  &::-webkit-scrollbar-thumb {
+    background: #99a9bf;
+    border-radius: 20px;
+  }
+}
+
+@mixin relative {
+  position: relative;
+  width: 100%;
+  height: 100%;
+}
+
+@mixin pct($pct) {
+  width: #{$pct};
+  position: relative;
+  margin: 0 auto;
+}
+
+@mixin triangle($width, $height, $color, $direction) {
+  $width: $width/2;
+  $color-border-style: $height solid $color;
+  $transparent-border-style: $width solid transparent;
+  height: 0;
+  width: 0;
+
+  @if $direction==up {
+    border-bottom: $color-border-style;
+    border-left: $transparent-border-style;
+    border-right: $transparent-border-style;
+  }
+
+  @else if $direction==right {
+    border-left: $color-border-style;
+    border-top: $transparent-border-style;
+    border-bottom: $transparent-border-style;
+  }
+
+  @else if $direction==down {
+    border-top: $color-border-style;
+    border-left: $transparent-border-style;
+    border-right: $transparent-border-style;
+  }
+
+  @else if $direction==left {
+    border-right: $color-border-style;
+    border-top: $transparent-border-style;
+    border-bottom: $transparent-border-style;
+  }
+}
diff --git a/jcdm-ui/src/assets/styles/ruoyi.scss b/jcdm-ui/src/assets/styles/ruoyi.scss
new file mode 100644
index 0000000..38f14a4
--- /dev/null
+++ b/jcdm-ui/src/assets/styles/ruoyi.scss
@@ -0,0 +1,291 @@
+/**
+* 閫氱敤css鏍峰紡甯冨眬澶勭悊
+* Copyright (c) 2019 jcdm
+*/
+
+/** 鍩虹閫氱敤 **/
+.pt5 {
+  padding-top: 5px;
+}
+
+.pr5 {
+  padding-right: 5px;
+}
+
+.pb5 {
+  padding-bottom: 5px;
+}
+
+.mt5 {
+  margin-top: 5px;
+}
+
+.mr5 {
+  margin-right: 5px;
+}
+
+.mb5 {
+  margin-bottom: 5px;
+}
+
+.mb8 {
+  margin-bottom: 8px;
+}
+
+.ml5 {
+  margin-left: 5px;
+}
+
+.mt10 {
+  margin-top: 10px;
+}
+
+.mr10 {
+  margin-right: 10px;
+}
+
+.mb10 {
+  margin-bottom: 10px;
+}
+.ml10 {
+	margin-left: 10px;
+}
+
+.mt20 {
+  margin-top: 20px;
+}
+
+.mr20 {
+  margin-right: 20px;
+}
+
+.mb20 {
+  margin-bottom: 20px;
+}
+.ml20 {
+	margin-left: 20px;
+}
+
+.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 {
+  font-family: inherit;
+  font-weight: 500;
+  line-height: 1.1;
+  color: inherit;
+}
+
+.el-message-box__status + .el-message-box__message{
+  word-break: break-word;
+}
+
+.el-dialog:not(.is-fullscreen) {
+  margin-top: 6vh !important;
+}
+
+.el-dialog__wrapper.scrollbar .el-dialog .el-dialog__body {
+  overflow: auto;
+  overflow-x: hidden;
+  max-height: 70vh;
+  padding: 10px 20px 0;
+}
+
+.el-table {
+  .el-table__header-wrapper, .el-table__fixed-header-wrapper {
+    th {
+      word-break: break-word;
+      background-color: #f8f8f9;
+      color: #515a6e;
+      height: 40px;
+      font-size: 13px;
+    }
+  }
+
+  .el-table__body-wrapper {
+    .el-button [class*="el-icon-"] + span {
+      margin-left: 1px;
+    }
+  }
+}
+
+/** 琛ㄥ崟甯冨眬 **/
+.form-header {
+  font-size: 15px;
+  color: #6379bb;
+  border-bottom: 1px solid #ddd;
+  margin: 8px 10px 25px 10px;
+  padding-bottom: 5px
+}
+
+/** 琛ㄦ牸甯冨眬 **/
+.pagination-container {
+  position: relative;
+  height: 25px;
+  margin-bottom: 10px;
+  margin-top: 15px;
+  padding: 10px 20px !important;
+}
+
+/* tree border */
+.tree-border {
+  margin-top: 5px;
+  border: 1px solid #e5e6e7;
+  background: #FFFFFF none;
+  border-radius: 4px;
+}
+
+.pagination-container .el-pagination {
+  right: 0;
+  position: absolute;
+}
+
+@media (max-width: 768px) {
+  .pagination-container .el-pagination > .el-pagination__jump {
+    display: none !important;
+  }
+  .pagination-container .el-pagination > .el-pagination__sizes {
+    display: none !important;
+  }
+}
+
+.el-table .fixed-width .el-button--mini {
+  padding-left: 0;
+  padding-right: 0;
+  width: inherit;
+}
+
+/** 琛ㄦ牸鏇村鎿嶄綔涓嬫媺鏍峰紡 */
+.el-table .el-dropdown-link,.el-table .el-dropdown-selfdefine {
+	cursor: pointer;
+	margin-left: 5px;
+}
+
+.el-table .el-dropdown, .el-icon-arrow-down {
+  font-size: 12px;
+}
+
+.el-tree-node__content > .el-checkbox {
+  margin-right: 8px;
+}
+
+.list-group-striped > .list-group-item {
+  border-left: 0;
+  border-right: 0;
+  border-radius: 0;
+  padding-left: 0;
+  padding-right: 0;
+}
+
+.list-group {
+  padding-left: 0px;
+  list-style: none;
+}
+
+.list-group-item {
+  border-bottom: 1px solid #e7eaec;
+  border-top: 1px solid #e7eaec;
+  margin-bottom: -1px;
+  padding: 11px 0px;
+  font-size: 13px;
+}
+
+.pull-right {
+  float: right !important;
+}
+
+.el-card__header {
+  padding: 14px 15px 7px;
+  min-height: 40px;
+}
+
+.el-card__body {
+  padding: 15px 20px 20px 20px;
+}
+
+.card-box {
+  padding-right: 15px;
+  padding-left: 15px;
+  margin-bottom: 10px;
+}
+
+/* button color */
+.el-button--cyan.is-active,
+.el-button--cyan:active {
+  background: #20B2AA;
+  border-color: #20B2AA;
+  color: #FFFFFF;
+}
+
+.el-button--cyan:focus,
+.el-button--cyan:hover {
+  background: #48D1CC;
+  border-color: #48D1CC;
+  color: #FFFFFF;
+}
+
+.el-button--cyan {
+  background-color: #20B2AA;
+  border-color: #20B2AA;
+  color: #FFFFFF;
+}
+
+/* text color */
+.text-navy {
+  color: #1ab394;
+}
+
+.text-primary {
+  color: inherit;
+}
+
+.text-success {
+  color: #1c84c6;
+}
+
+.text-info {
+  color: #23c6c8;
+}
+
+.text-warning {
+  color: #f8ac59;
+}
+
+.text-danger {
+  color: #ed5565;
+}
+
+.text-muted {
+  color: #888888;
+}
+
+/* image */
+.img-circle {
+  border-radius: 50%;
+}
+
+.img-lg {
+  width: 120px;
+  height: 120px;
+}
+
+.avatar-upload-preview {
+  position: relative;
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+  width: 200px;
+  height: 200px;
+  border-radius: 50%;
+  box-shadow: 0 0 4px #ccc;
+  overflow: hidden;
+}
+
+/* 鎷栨嫿鍒楁牱寮� */
+.sortable-ghost {
+  opacity: .8;
+  color: #fff !important;
+  background: #42b983 !important;
+}
+
+.top-right-btn {
+  position: relative;
+  float: right;
+}
diff --git a/jcdm-ui/src/assets/styles/sidebar.scss b/jcdm-ui/src/assets/styles/sidebar.scss
new file mode 100644
index 0000000..abe5b63
--- /dev/null
+++ b/jcdm-ui/src/assets/styles/sidebar.scss
@@ -0,0 +1,227 @@
+#app {
+
+  .main-container {
+    height: 100%;
+    transition: margin-left .28s;
+    margin-left: $base-sidebar-width;
+    position: relative;
+  }
+
+  .sidebarHide {
+    margin-left: 0!important;
+  }
+
+  .sidebar-container {
+    -webkit-transition: width .28s;
+    transition: width 0.28s;
+    width: $base-sidebar-width !important;
+    background-color: $base-menu-background;
+    height: 100%;
+    position: fixed;
+    font-size: 0px;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    z-index: 1001;
+    overflow: hidden;
+    -webkit-box-shadow: 2px 0 6px rgba(0,21,41,.35);
+    box-shadow: 2px 0 6px rgba(0,21,41,.35);
+
+    // reset element-ui css
+    .horizontal-collapse-transition {
+      transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
+    }
+
+    .scrollbar-wrapper {
+      overflow-x: hidden !important;
+    }
+
+    .el-scrollbar__bar.is-vertical {
+      right: 0px;
+    }
+
+    .el-scrollbar {
+      height: 100%;
+    }
+
+    &.has-logo {
+      .el-scrollbar {
+        height: calc(100% - 50px);
+      }
+    }
+
+    .is-horizontal {
+      display: none;
+    }
+
+    a {
+      display: inline-block;
+      width: 100%;
+      overflow: hidden;
+    }
+
+    .svg-icon {
+      margin-right: 16px;
+    }
+
+    .el-menu {
+      border: none;
+      height: 100%;
+      width: 100% !important;
+    }
+
+    .el-menu-item, .el-submenu__title {
+      overflow: hidden !important;
+      text-overflow: ellipsis !important;
+      white-space: nowrap !important;
+    }
+
+    // menu hover
+    .submenu-title-noDropdown,
+    .el-submenu__title {
+      &:hover {
+        background-color: rgba(0, 0, 0, 0.06) !important;
+      }
+    }
+
+    & .theme-dark .is-active > .el-submenu__title {
+      color: $base-menu-color-active !important;
+    }
+
+    & .nest-menu .el-submenu>.el-submenu__title,
+    & .el-submenu .el-menu-item {
+      min-width: $base-sidebar-width !important;
+
+      &:hover {
+        background-color: rgba(0, 0, 0, 0.06) !important;
+      }
+    }
+
+    & .theme-dark .nest-menu .el-submenu>.el-submenu__title,
+    & .theme-dark .el-submenu .el-menu-item {
+      background-color: $base-sub-menu-background !important;
+
+      &:hover {
+        background-color: $base-sub-menu-hover !important;
+      }
+    }
+  }
+
+  .hideSidebar {
+    .sidebar-container {
+      width: 54px !important;
+    }
+
+    .main-container {
+      margin-left: 54px;
+    }
+
+    .submenu-title-noDropdown {
+      padding: 0 !important;
+      position: relative;
+
+      .el-tooltip {
+        padding: 0 !important;
+
+        .svg-icon {
+          margin-left: 20px;
+        }
+      }
+    }
+
+    .el-submenu {
+      overflow: hidden;
+
+      &>.el-submenu__title {
+        padding: 0 !important;
+
+        .svg-icon {
+          margin-left: 20px;
+        }
+
+      }
+    }
+
+    .el-menu--collapse {
+      .el-submenu {
+        &>.el-submenu__title {
+          &>span {
+            height: 0;
+            width: 0;
+            overflow: hidden;
+            visibility: hidden;
+            display: inline-block;
+          }
+        }
+      }
+    }
+  }
+
+  .el-menu--collapse .el-menu .el-submenu {
+    min-width: $base-sidebar-width !important;
+  }
+
+  // mobile responsive
+  .mobile {
+    .main-container {
+      margin-left: 0px;
+    }
+
+    .sidebar-container {
+      transition: transform .28s;
+      width: $base-sidebar-width !important;
+    }
+
+    &.hideSidebar {
+      .sidebar-container {
+        pointer-events: none;
+        transition-duration: 0.3s;
+        transform: translate3d(-$base-sidebar-width, 0, 0);
+      }
+    }
+  }
+
+  .withoutAnimation {
+
+    .main-container,
+    .sidebar-container {
+      transition: none;
+    }
+  }
+}
+
+// when menu collapsed
+.el-menu--vertical {
+  &>.el-menu {
+    .svg-icon {
+      margin-right: 16px;
+    }
+  }
+
+  .nest-menu .el-submenu>.el-submenu__title,
+  .el-menu-item {
+    &:hover {
+      // you can use $subMenuHover
+      background-color: rgba(0, 0, 0, 0.06) !important;
+    }
+  }
+
+  // the scroll bar appears when the subMenu is too long
+  >.el-menu--popup {
+    max-height: 100vh;
+    overflow-y: auto;
+
+    &::-webkit-scrollbar-track-piece {
+      background: #d3dce6;
+    }
+
+    &::-webkit-scrollbar {
+      width: 6px;
+    }
+
+    &::-webkit-scrollbar-thumb {
+      background: #99a9bf;
+      border-radius: 20px;
+    }
+  }
+}
diff --git a/jcdm-ui/src/assets/styles/transition.scss b/jcdm-ui/src/assets/styles/transition.scss
new file mode 100644
index 0000000..073f8c6
--- /dev/null
+++ b/jcdm-ui/src/assets/styles/transition.scss
@@ -0,0 +1,49 @@
+// global transition css
+
+/* fade */
+.fade-enter-active,
+.fade-leave-active {
+  transition: opacity 0.28s;
+}
+
+.fade-enter,
+.fade-leave-active {
+  opacity: 0;
+}
+
+/* fade-transform */
+.fade-transform--move,
+.fade-transform-leave-active,
+.fade-transform-enter-active {
+  transition: all .5s;
+}
+
+.fade-transform-enter {
+  opacity: 0;
+  transform: translateX(-30px);
+}
+
+.fade-transform-leave-to {
+  opacity: 0;
+  transform: translateX(30px);
+}
+
+/* breadcrumb transition */
+.breadcrumb-enter-active,
+.breadcrumb-leave-active {
+  transition: all .5s;
+}
+
+.breadcrumb-enter,
+.breadcrumb-leave-active {
+  opacity: 0;
+  transform: translateX(20px);
+}
+
+.breadcrumb-move {
+  transition: all .5s;
+}
+
+.breadcrumb-leave-active {
+  position: absolute;
+}
diff --git a/jcdm-ui/src/assets/styles/variables.scss b/jcdm-ui/src/assets/styles/variables.scss
new file mode 100644
index 0000000..8d4b452
--- /dev/null
+++ b/jcdm-ui/src/assets/styles/variables.scss
@@ -0,0 +1,54 @@
+// base color
+$blue:#324157;
+$light-blue:#3A71A8;
+$red:#C03639;
+$pink: #E65D6E;
+$green: #30B08F;
+$tiffany: #4AB7BD;
+$yellow:#FEC171;
+$panGreen: #30B08F;
+
+// 榛樿鑿滃崟涓婚椋庢牸
+$base-menu-color:#bfcbd9;
+$base-menu-color-active:#f4f4f5;
+$base-menu-background: #011e2d;
+$base-logo-title-color: #ffffff;
+
+$base-menu-light-color:rgba(0,0,0,.70);
+$base-menu-light-background:#ffffff;
+$base-logo-light-title-color: #001529;
+
+$base-sub-menu-background:#1f2d3d;
+$base-sub-menu-hover:#001528;
+
+// 鑷畾涔夋殫鑹茶彍鍗曢鏍�
+/**
+$base-menu-color:hsla(0,0%,100%,.65);
+$base-menu-color-active:#fff;
+$base-menu-background:#001529;
+$base-logo-title-color: #ffffff;
+
+$base-menu-light-color:rgba(0,0,0,.70);
+$base-menu-light-background:#ffffff;
+$base-logo-light-title-color: #001529;
+
+$base-sub-menu-background:#000c17;
+$base-sub-menu-hover:#001528;
+*/
+
+$base-sidebar-width: 200px;
+
+// the :export directive is the magic sauce for webpack
+// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
+:export {
+  menuColor: $base-menu-color;
+  menuLightColor: $base-menu-light-color;
+  menuColorActive: $base-menu-color-active;
+  menuBackground: $base-menu-background;
+  menuLightBackground: $base-menu-light-background;
+  subMenuBackground: $base-sub-menu-background;
+  subMenuHover: $base-sub-menu-hover;
+  sideBarWidth: $base-sidebar-width;
+  logoTitleColor: $base-logo-title-color;
+  logoLightTitleColor: $base-logo-light-title-color
+}
diff --git a/jcdm-ui/src/components/Breadcrumb/index.vue b/jcdm-ui/src/components/Breadcrumb/index.vue
new file mode 100644
index 0000000..1696f54
--- /dev/null
+++ b/jcdm-ui/src/components/Breadcrumb/index.vue
@@ -0,0 +1,74 @@
+<template>
+  <el-breadcrumb class="app-breadcrumb" separator="/">
+    <transition-group name="breadcrumb">
+      <el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path">
+        <span v-if="item.redirect === 'noRedirect' || index == levelList.length - 1" class="no-redirect">{{ item.meta.title }}</span>
+        <a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
+      </el-breadcrumb-item>
+    </transition-group>
+  </el-breadcrumb>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      levelList: null
+    }
+  },
+  watch: {
+    $route(route) {
+      // if you go to the redirect page, do not update the breadcrumbs
+      if (route.path.startsWith('/redirect/')) {
+        return
+      }
+      this.getBreadcrumb()
+    }
+  },
+  created() {
+    this.getBreadcrumb()
+  },
+  methods: {
+    getBreadcrumb() {
+      // only show routes with meta.title
+      let matched = this.$route.matched.filter(item => item.meta && item.meta.title)
+      const first = matched[0]
+
+      if (!this.isDashboard(first)) {
+        matched = [{ path: '/index', meta: { title: '棣栭〉' }}].concat(matched)
+      }
+
+      this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
+    },
+    isDashboard(route) {
+      const name = route && route.name
+      if (!name) {
+        return false
+      }
+      return name.trim() === 'Index'
+    },
+    handleLink(item) {
+      const { redirect, path } = item
+      if (redirect) {
+        this.$router.push(redirect)
+        return
+      }
+      this.$router.push(path)
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.app-breadcrumb.el-breadcrumb {
+  display: inline-block;
+  font-size: 14px;
+  line-height: 50px;
+  margin-left: 8px;
+
+  .no-redirect {
+    color: #97a8be;
+    cursor: text;
+  }
+}
+</style>
diff --git a/jcdm-ui/src/components/Crontab/day.vue b/jcdm-ui/src/components/Crontab/day.vue
new file mode 100644
index 0000000..fe3eaf0
--- /dev/null
+++ b/jcdm-ui/src/components/Crontab/day.vue
@@ -0,0 +1,161 @@
+<template>
+	<el-form size="small">
+		<el-form-item>
+			<el-radio v-model='radioValue' :label="1">
+				鏃ワ紝鍏佽鐨勯�氶厤绗, - * ? / L W]
+			</el-radio>
+		</el-form-item>
+
+		<el-form-item>
+			<el-radio v-model='radioValue' :label="2">
+				涓嶆寚瀹�
+			</el-radio>
+		</el-form-item>
+
+		<el-form-item>
+			<el-radio v-model='radioValue' :label="3">
+				鍛ㄦ湡浠�
+				<el-input-number v-model='cycle01' :min="1" :max="30" /> -
+				<el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 2" :max="31" /> 鏃�
+			</el-radio>
+		</el-form-item>
+
+		<el-form-item>
+			<el-radio v-model='radioValue' :label="4">
+				浠�
+				<el-input-number v-model='average01' :min="1" :max="30" /> 鍙峰紑濮嬶紝姣�
+				<el-input-number v-model='average02' :min="1" :max="31 - average01 || 1" /> 鏃ユ墽琛屼竴娆�
+			</el-radio>
+		</el-form-item>
+
+		<el-form-item>
+			<el-radio v-model='radioValue' :label="5">
+				姣忔湀
+				<el-input-number v-model='workday' :min="1" :max="31" /> 鍙锋渶杩戠殑閭d釜宸ヤ綔鏃�
+			</el-radio>
+		</el-form-item>
+
+		<el-form-item>
+			<el-radio v-model='radioValue' :label="6">
+				鏈湀鏈�鍚庝竴澶�
+			</el-radio>
+		</el-form-item>
+
+		<el-form-item>
+			<el-radio v-model='radioValue' :label="7">
+				鎸囧畾
+				<el-select clearable v-model="checkboxList" placeholder="鍙閫�" multiple style="width:100%">
+					<el-option v-for="item in 31" :key="item" :value="item">{{item}}</el-option>
+				</el-select>
+			</el-radio>
+		</el-form-item>
+	</el-form>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			radioValue: 1,
+			workday: 1,
+			cycle01: 1,
+			cycle02: 2,
+			average01: 1,
+			average02: 1,
+			checkboxList: [],
+			checkNum: this.$options.propsData.check
+		}
+	},
+	name: 'crontab-day',
+	props: ['check', 'cron'],
+	methods: {
+		// 鍗曢�夋寜閽�煎彉鍖栨椂
+		radioChange() {
+			('day rachange');
+			if (this.radioValue !== 2 && this.cron.week !== '?') {
+				this.$emit('update', 'week', '?', 'day')
+			}
+
+			switch (this.radioValue) {
+				case 1:
+					this.$emit('update', 'day', '*');
+					break;
+				case 2:
+					this.$emit('update', 'day', '?');
+					break;
+				case 3:
+					this.$emit('update', 'day', this.cycleTotal);
+					break;
+				case 4:
+					this.$emit('update', 'day', this.averageTotal);
+					break;
+				case 5:
+					this.$emit('update', 'day', this.workday + 'W');
+					break;
+				case 6:
+					this.$emit('update', 'day', 'L');
+					break;
+				case 7:
+					this.$emit('update', 'day', this.checkboxString);
+					break;
+			}
+			('day rachange end');
+		},
+		// 鍛ㄦ湡涓や釜鍊煎彉鍖栨椂
+		cycleChange() {
+			if (this.radioValue == '3') {
+				this.$emit('update', 'day', this.cycleTotal);
+			}
+		},
+		// 骞冲潎涓や釜鍊煎彉鍖栨椂
+		averageChange() {
+			if (this.radioValue == '4') {
+				this.$emit('update', 'day', this.averageTotal);
+			}
+		},
+		// 鏈�杩戝伐浣滄棩鍊煎彉鍖栨椂
+		workdayChange() {
+			if (this.radioValue == '5') {
+				this.$emit('update', 'day', this.workdayCheck + 'W');
+			}
+		},
+		// checkbox鍊煎彉鍖栨椂
+		checkboxChange() {
+			if (this.radioValue == '7') {
+				this.$emit('update', 'day', this.checkboxString);
+			}
+		}
+	},
+	watch: {
+		'radioValue': 'radioChange',
+		'cycleTotal': 'cycleChange',
+		'averageTotal': 'averageChange',
+		'workdayCheck': 'workdayChange',
+		'checkboxString': 'checkboxChange',
+	},
+	computed: {
+		// 璁$畻涓や釜鍛ㄦ湡鍊�
+		cycleTotal: function () {
+			const cycle01 = this.checkNum(this.cycle01, 1, 30)
+			const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 2, 31, 31)
+			return cycle01 + '-' + cycle02;
+		},
+		// 璁$畻骞冲潎鐢ㄥ埌鐨勫��
+		averageTotal: function () {
+			const average01 = this.checkNum(this.average01, 1, 30)
+			const average02 = this.checkNum(this.average02, 1, 31 - average01 || 0)
+			return average01 + '/' + average02;
+		},
+		// 璁$畻宸ヤ綔鏃ユ牸寮�
+		workdayCheck: function () {
+			const workday = this.checkNum(this.workday, 1, 31)
+			return workday;
+		},
+		// 璁$畻鍕鹃�夌殑checkbox鍊煎悎闆�
+		checkboxString: function () {
+			let str = this.checkboxList.join();
+			return str == '' ? '*' : str;
+		}
+	}
+}
+</script>
diff --git a/jcdm-ui/src/components/Crontab/hour.vue b/jcdm-ui/src/components/Crontab/hour.vue
new file mode 100644
index 0000000..4b1f1fc
--- /dev/null
+++ b/jcdm-ui/src/components/Crontab/hour.vue
@@ -0,0 +1,114 @@
+<template>
+	<el-form size="small">
+		<el-form-item>
+			<el-radio v-model='radioValue' :label="1">
+				灏忔椂锛屽厑璁哥殑閫氶厤绗, - * /]
+			</el-radio>
+		</el-form-item>
+
+		<el-form-item>
+			<el-radio v-model='radioValue' :label="2">
+				鍛ㄦ湡浠�
+				<el-input-number v-model='cycle01' :min="0" :max="22" /> -
+				<el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 1" :max="23" /> 灏忔椂
+			</el-radio>
+		</el-form-item>
+
+		<el-form-item>
+			<el-radio v-model='radioValue' :label="3">
+				浠�
+				<el-input-number v-model='average01' :min="0" :max="22" /> 灏忔椂寮�濮嬶紝姣�
+				<el-input-number v-model='average02' :min="1" :max="23 - average01 || 0" /> 灏忔椂鎵ц涓�娆�
+			</el-radio>
+		</el-form-item>
+
+		<el-form-item>
+			<el-radio v-model='radioValue' :label="4">
+				鎸囧畾
+				<el-select clearable v-model="checkboxList" placeholder="鍙閫�" multiple style="width:100%">
+					<el-option v-for="item in 24" :key="item" :value="item-1">{{item-1}}</el-option>
+				</el-select>
+			</el-radio>
+		</el-form-item>
+	</el-form>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			radioValue: 1,
+			cycle01: 0,
+			cycle02: 1,
+			average01: 0,
+			average02: 1,
+			checkboxList: [],
+			checkNum: this.$options.propsData.check
+		}
+	},
+	name: 'crontab-hour',
+	props: ['check', 'cron'],
+	methods: {
+		// 鍗曢�夋寜閽�煎彉鍖栨椂
+		radioChange() {
+			switch (this.radioValue) {
+				case 1:
+        	this.$emit('update', 'hour', '*')
+        	break;
+				case 2:
+					this.$emit('update', 'hour', this.cycleTotal);
+					break;
+				case 3:
+					this.$emit('update', 'hour', this.averageTotal);
+					break;
+				case 4:
+					this.$emit('update', 'hour', this.checkboxString);
+					break;
+			}
+		},
+		// 鍛ㄦ湡涓や釜鍊煎彉鍖栨椂
+		cycleChange() {
+			if (this.radioValue == '2') {
+				this.$emit('update', 'hour', this.cycleTotal);
+			}
+		},
+		// 骞冲潎涓や釜鍊煎彉鍖栨椂
+		averageChange() {
+			if (this.radioValue == '3') {
+				this.$emit('update', 'hour', this.averageTotal);
+			}
+		},
+		// checkbox鍊煎彉鍖栨椂
+		checkboxChange() {
+			if (this.radioValue == '4') {
+				this.$emit('update', 'hour', this.checkboxString);
+			}
+		}
+	},
+	watch: {
+		'radioValue': 'radioChange',
+		'cycleTotal': 'cycleChange',
+		'averageTotal': 'averageChange',
+		'checkboxString': 'checkboxChange'
+	},
+	computed: {
+		// 璁$畻涓や釜鍛ㄦ湡鍊�
+		cycleTotal: function () {
+			const cycle01 = this.checkNum(this.cycle01, 0, 22)
+			const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 1, 23)
+			return cycle01 + '-' + cycle02;
+		},
+		// 璁$畻骞冲潎鐢ㄥ埌鐨勫��
+		averageTotal: function () {
+			const average01 = this.checkNum(this.average01, 0, 22)
+			const average02 = this.checkNum(this.average02, 1, 23 - average01 || 0)
+			return average01 + '/' + average02;
+		},
+		// 璁$畻鍕鹃�夌殑checkbox鍊煎悎闆�
+		checkboxString: function () {
+			let str = this.checkboxList.join();
+			return str == '' ? '*' : str;
+		}
+	}
+}
+</script>
diff --git a/jcdm-ui/src/components/Crontab/index.vue b/jcdm-ui/src/components/Crontab/index.vue
new file mode 100644
index 0000000..3963df2
--- /dev/null
+++ b/jcdm-ui/src/components/Crontab/index.vue
@@ -0,0 +1,430 @@
+<template>
+  <div>
+    <el-tabs type="border-card">
+      <el-tab-pane label="绉�" v-if="shouldHide('second')">
+        <CrontabSecond
+          @update="updateCrontabValue"
+          :check="checkNumber"
+          :cron="crontabValueObj"
+          ref="cronsecond"
+        />
+      </el-tab-pane>
+
+      <el-tab-pane label="鍒嗛挓" v-if="shouldHide('min')">
+        <CrontabMin
+          @update="updateCrontabValue"
+          :check="checkNumber"
+          :cron="crontabValueObj"
+          ref="cronmin"
+        />
+      </el-tab-pane>
+
+      <el-tab-pane label="灏忔椂" v-if="shouldHide('hour')">
+        <CrontabHour
+          @update="updateCrontabValue"
+          :check="checkNumber"
+          :cron="crontabValueObj"
+          ref="cronhour"
+        />
+      </el-tab-pane>
+
+      <el-tab-pane label="鏃�" v-if="shouldHide('day')">
+        <CrontabDay
+          @update="updateCrontabValue"
+          :check="checkNumber"
+          :cron="crontabValueObj"
+          ref="cronday"
+        />
+      </el-tab-pane>
+
+      <el-tab-pane label="鏈�" v-if="shouldHide('month')">
+        <CrontabMonth
+          @update="updateCrontabValue"
+          :check="checkNumber"
+          :cron="crontabValueObj"
+          ref="cronmonth"
+        />
+      </el-tab-pane>
+
+      <el-tab-pane label="鍛�" v-if="shouldHide('week')">
+        <CrontabWeek
+          @update="updateCrontabValue"
+          :check="checkNumber"
+          :cron="crontabValueObj"
+          ref="cronweek"
+        />
+      </el-tab-pane>
+
+      <el-tab-pane label="骞�" v-if="shouldHide('year')">
+        <CrontabYear
+          @update="updateCrontabValue"
+          :check="checkNumber"
+          :cron="crontabValueObj"
+          ref="cronyear"
+        />
+      </el-tab-pane>
+    </el-tabs>
+
+    <div class="popup-main">
+      <div class="popup-result">
+        <p class="title">鏃堕棿琛ㄨ揪寮�</p>
+        <table>
+          <thead>
+            <th v-for="item of tabTitles" width="40" :key="item">{{item}}</th>
+            <th>Cron 琛ㄨ揪寮�</th>
+          </thead>
+          <tbody>
+            <td>
+              <span>{{crontabValueObj.second}}</span>
+            </td>
+            <td>
+              <span>{{crontabValueObj.min}}</span>
+            </td>
+            <td>
+              <span>{{crontabValueObj.hour}}</span>
+            </td>
+            <td>
+              <span>{{crontabValueObj.day}}</span>
+            </td>
+            <td>
+              <span>{{crontabValueObj.month}}</span>
+            </td>
+            <td>
+              <span>{{crontabValueObj.week}}</span>
+            </td>
+            <td>
+              <span>{{crontabValueObj.year}}</span>
+            </td>
+            <td>
+              <span>{{crontabValueString}}</span>
+            </td>
+          </tbody>
+        </table>
+      </div>
+      <CrontabResult :ex="crontabValueString"></CrontabResult>
+
+      <div class="pop_btn">
+        <el-button size="small" type="primary" @click="submitFill">纭畾</el-button>
+        <el-button size="small" type="warning" @click="clearCron">閲嶇疆</el-button>
+        <el-button size="small" @click="hidePopup">鍙栨秷</el-button>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import CrontabSecond from "./second.vue";
+import CrontabMin from "./min.vue";
+import CrontabHour from "./hour.vue";
+import CrontabDay from "./day.vue";
+import CrontabMonth from "./month.vue";
+import CrontabWeek from "./week.vue";
+import CrontabYear from "./year.vue";
+import CrontabResult from "./result.vue";
+
+export default {
+  data() {
+    return {
+      tabTitles: ["绉�", "鍒嗛挓", "灏忔椂", "鏃�", "鏈�", "鍛�", "骞�"],
+      tabActive: 0,
+      myindex: 0,
+      crontabValueObj: {
+        second: "*",
+        min: "*",
+        hour: "*",
+        day: "*",
+        month: "*",
+        week: "?",
+        year: "",
+      },
+    };
+  },
+  name: "vcrontab",
+  props: ["expression", "hideComponent"],
+  methods: {
+    shouldHide(key) {
+      if (this.hideComponent && this.hideComponent.includes(key)) return false;
+      return true;
+    },
+    resolveExp() {
+      // 鍙嶈В鏋� 琛ㄨ揪寮�
+      if (this.expression) {
+        let arr = this.expression.split(" ");
+        if (arr.length >= 6) {
+          //6 浣嶄互涓婃槸鍚堟硶琛ㄨ揪寮�
+          let obj = {
+            second: arr[0],
+            min: arr[1],
+            hour: arr[2],
+            day: arr[3],
+            month: arr[4],
+            week: arr[5],
+            year: arr[6] ? arr[6] : "",
+          };
+          this.crontabValueObj = {
+            ...obj,
+          };
+          for (let i in obj) {
+            if (obj[i]) this.changeRadio(i, obj[i]);
+          }
+        }
+      } else {
+        // 娌℃湁浼犲叆鐨勮〃杈惧紡 鍒欒繕鍘�
+        this.clearCron();
+      }
+    },
+    // tab鍒囨崲鍊�
+    tabCheck(index) {
+      this.tabActive = index;
+    },
+    // 鐢卞瓙缁勪欢瑙﹀彂锛屾洿鏀硅〃杈惧紡缁勬垚鐨勫瓧娈靛��
+    updateCrontabValue(name, value, from) {
+      "updateCrontabValue", name, value, from;
+      this.crontabValueObj[name] = value;
+      if (from && from !== name) {
+        console.log(`鏉ヨ嚜缁勪欢 ${from} 鏀瑰彉浜� ${name} ${value}`);
+        this.changeRadio(name, value);
+      }
+    },
+    // 璧嬪�煎埌缁勪欢
+    changeRadio(name, value) {
+      let arr = ["second", "min", "hour", "month"],
+        refName = "cron" + name,
+        insValue;
+
+      if (!this.$refs[refName]) return;
+
+      if (arr.includes(name)) {
+        if (value === "*") {
+          insValue = 1;
+        } else if (value.indexOf("-") > -1) {
+          let indexArr = value.split("-");
+          isNaN(indexArr[0])
+            ? (this.$refs[refName].cycle01 = 0)
+            : (this.$refs[refName].cycle01 = indexArr[0]);
+          this.$refs[refName].cycle02 = indexArr[1];
+          insValue = 2;
+        } else if (value.indexOf("/") > -1) {
+          let indexArr = value.split("/");
+          isNaN(indexArr[0])
+            ? (this.$refs[refName].average01 = 0)
+            : (this.$refs[refName].average01 = indexArr[0]);
+          this.$refs[refName].average02 = indexArr[1];
+          insValue = 3;
+        } else {
+          insValue = 4;
+          this.$refs[refName].checkboxList = value.split(",");
+        }
+      } else if (name == "day") {
+        if (value === "*") {
+          insValue = 1;
+        } else if (value == "?") {
+          insValue = 2;
+        } else if (value.indexOf("-") > -1) {
+          let indexArr = value.split("-");
+          isNaN(indexArr[0])
+            ? (this.$refs[refName].cycle01 = 0)
+            : (this.$refs[refName].cycle01 = indexArr[0]);
+          this.$refs[refName].cycle02 = indexArr[1];
+          insValue = 3;
+        } else if (value.indexOf("/") > -1) {
+          let indexArr = value.split("/");
+          isNaN(indexArr[0])
+            ? (this.$refs[refName].average01 = 0)
+            : (this.$refs[refName].average01 = indexArr[0]);
+          this.$refs[refName].average02 = indexArr[1];
+          insValue = 4;
+        } else if (value.indexOf("W") > -1) {
+          let indexArr = value.split("W");
+          isNaN(indexArr[0])
+            ? (this.$refs[refName].workday = 0)
+            : (this.$refs[refName].workday = indexArr[0]);
+          insValue = 5;
+        } else if (value === "L") {
+          insValue = 6;
+        } else {
+          this.$refs[refName].checkboxList = value.split(",");
+          insValue = 7;
+        }
+      } else if (name == "week") {
+        if (value === "*") {
+          insValue = 1;
+        } else if (value == "?") {
+          insValue = 2;
+        } else if (value.indexOf("-") > -1) {
+          let indexArr = value.split("-");
+          isNaN(indexArr[0])
+            ? (this.$refs[refName].cycle01 = 0)
+            : (this.$refs[refName].cycle01 = indexArr[0]);
+          this.$refs[refName].cycle02 = indexArr[1];
+          insValue = 3;
+        } else if (value.indexOf("#") > -1) {
+          let indexArr = value.split("#");
+          isNaN(indexArr[0])
+            ? (this.$refs[refName].average01 = 1)
+            : (this.$refs[refName].average01 = indexArr[0]);
+          this.$refs[refName].average02 = indexArr[1];
+          insValue = 4;
+        } else if (value.indexOf("L") > -1) {
+          let indexArr = value.split("L");
+          isNaN(indexArr[0])
+            ? (this.$refs[refName].weekday = 1)
+            : (this.$refs[refName].weekday = indexArr[0]);
+          insValue = 5;
+        } else {
+          this.$refs[refName].checkboxList = value.split(",");
+          insValue = 6;
+        }
+      } else if (name == "year") {
+        if (value == "") {
+          insValue = 1;
+        } else if (value == "*") {
+          insValue = 2;
+        } else if (value.indexOf("-") > -1) {
+          insValue = 3;
+        } else if (value.indexOf("/") > -1) {
+          insValue = 4;
+        } else {
+          this.$refs[refName].checkboxList = value.split(",");
+          insValue = 5;
+        }
+      }
+      this.$refs[refName].radioValue = insValue;
+    },
+    // 琛ㄥ崟閫夐」鐨勫瓙缁勪欢鏍¢獙鏁板瓧鏍煎紡锛堥�氳繃-props浼犻�掞級
+    checkNumber(value, minLimit, maxLimit) {
+      // 妫�鏌ュ繀椤讳负鏁存暟
+      value = Math.floor(value);
+      if (value < minLimit) {
+        value = minLimit;
+      } else if (value > maxLimit) {
+        value = maxLimit;
+      }
+      return value;
+    },
+    // 闅愯棌寮圭獥
+    hidePopup() {
+      this.$emit("hide");
+    },
+    // 濉厖琛ㄨ揪寮�
+    submitFill() {
+      this.$emit("fill", this.crontabValueString);
+      this.hidePopup();
+    },
+    clearCron() {
+      // 杩樺師閫夋嫨椤�
+      ("鍑嗗杩樺師");
+      this.crontabValueObj = {
+        second: "*",
+        min: "*",
+        hour: "*",
+        day: "*",
+        month: "*",
+        week: "?",
+        year: "",
+      };
+      for (let j in this.crontabValueObj) {
+        this.changeRadio(j, this.crontabValueObj[j]);
+      }
+    },
+  },
+  computed: {
+    crontabValueString: function() {
+      let obj = this.crontabValueObj;
+      let str =
+        obj.second +
+        " " +
+        obj.min +
+        " " +
+        obj.hour +
+        " " +
+        obj.day +
+        " " +
+        obj.month +
+        " " +
+        obj.week +
+        (obj.year == "" ? "" : " " + obj.year);
+      return str;
+    },
+  },
+  components: {
+    CrontabSecond,
+    CrontabMin,
+    CrontabHour,
+    CrontabDay,
+    CrontabMonth,
+    CrontabWeek,
+    CrontabYear,
+    CrontabResult,
+  },
+  watch: {
+    expression: "resolveExp",
+    hideComponent(value) {
+      // 闅愯棌閮ㄥ垎缁勪欢
+    },
+  },
+  mounted: function() {
+    this.resolveExp();
+  },
+};
+</script>
+<style scoped>
+.pop_btn {
+  text-align: center;
+  margin-top: 20px;
+}
+.popup-main {
+  position: relative;
+  margin: 10px auto;
+  background: #fff;
+  border-radius: 5px;
+  font-size: 12px;
+  overflow: hidden;
+}
+.popup-title {
+  overflow: hidden;
+  line-height: 34px;
+  padding-top: 6px;
+  background: #f2f2f2;
+}
+.popup-result {
+  box-sizing: border-box;
+  line-height: 24px;
+  margin: 25px auto;
+  padding: 15px 10px 10px;
+  border: 1px solid #ccc;
+  position: relative;
+}
+.popup-result .title {
+  position: absolute;
+  top: -28px;
+  left: 50%;
+  width: 140px;
+  font-size: 14px;
+  margin-left: -70px;
+  text-align: center;
+  line-height: 30px;
+  background: #fff;
+}
+.popup-result table {
+  text-align: center;
+  width: 100%;
+  margin: 0 auto;
+}
+.popup-result table span {
+  display: block;
+  width: 100%;
+  font-family: arial;
+  line-height: 30px;
+  height: 30px;
+  white-space: nowrap;
+  overflow: hidden;
+  border: 1px solid #e8e8e8;
+}
+.popup-result-scroll {
+  font-size: 12px;
+  line-height: 24px;
+  height: 10em;
+  overflow-y: auto;
+}
+</style>
diff --git a/jcdm-ui/src/components/Crontab/min.vue b/jcdm-ui/src/components/Crontab/min.vue
new file mode 100644
index 0000000..43cab90
--- /dev/null
+++ b/jcdm-ui/src/components/Crontab/min.vue
@@ -0,0 +1,116 @@
+<template>
+	<el-form size="small">
+		<el-form-item>
+			<el-radio v-model='radioValue' :label="1">
+				鍒嗛挓锛屽厑璁哥殑閫氶厤绗, - * /]
+			</el-radio>
+		</el-form-item>
+
+		<el-form-item>
+			<el-radio v-model='radioValue' :label="2">
+				鍛ㄦ湡浠�
+				<el-input-number v-model='cycle01' :min="0" :max="58" /> -
+				<el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 1" :max="59" /> 鍒嗛挓
+			</el-radio>
+		</el-form-item>
+
+		<el-form-item>
+			<el-radio v-model='radioValue' :label="3">
+				浠�
+				<el-input-number v-model='average01' :min="0" :max="58" /> 鍒嗛挓寮�濮嬶紝姣�
+				<el-input-number v-model='average02' :min="1" :max="59 - average01 || 0" /> 鍒嗛挓鎵ц涓�娆�
+			</el-radio>
+		</el-form-item>
+
+		<el-form-item>
+			<el-radio v-model='radioValue' :label="4">
+				鎸囧畾
+				<el-select clearable v-model="checkboxList" placeholder="鍙閫�" multiple style="width:100%">
+					<el-option v-for="item in 60" :key="item" :value="item-1">{{item-1}}</el-option>
+				</el-select>
+			</el-radio>
+		</el-form-item>
+	</el-form>
+
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			radioValue: 1,
+			cycle01: 1,
+			cycle02: 2,
+			average01: 0,
+			average02: 1,
+			checkboxList: [],
+			checkNum: this.$options.propsData.check
+		}
+	},
+	name: 'crontab-min',
+	props: ['check', 'cron'],
+	methods: {
+		// 鍗曢�夋寜閽�煎彉鍖栨椂
+		radioChange() {
+			switch (this.radioValue) {
+				case 1:
+					this.$emit('update', 'min', '*', 'min');
+					break;
+				case 2:
+					this.$emit('update', 'min', this.cycleTotal, 'min');
+					break;
+				case 3:
+					this.$emit('update', 'min', this.averageTotal, 'min');
+					break;
+				case 4:
+					this.$emit('update', 'min', this.checkboxString, 'min');
+					break;
+			}
+		},
+		// 鍛ㄦ湡涓や釜鍊煎彉鍖栨椂
+		cycleChange() {
+			if (this.radioValue == '2') {
+				this.$emit('update', 'min', this.cycleTotal, 'min');
+			}
+		},
+		// 骞冲潎涓や釜鍊煎彉鍖栨椂
+		averageChange() {
+			if (this.radioValue == '3') {
+				this.$emit('update', 'min', this.averageTotal, 'min');
+			}
+		},
+		// checkbox鍊煎彉鍖栨椂
+		checkboxChange() {
+			if (this.radioValue == '4') {
+				this.$emit('update', 'min', this.checkboxString, 'min');
+			}
+		},
+
+	},
+	watch: {
+		'radioValue': 'radioChange',
+		'cycleTotal': 'cycleChange',
+		'averageTotal': 'averageChange',
+		'checkboxString': 'checkboxChange',
+	},
+	computed: {
+		// 璁$畻涓や釜鍛ㄦ湡鍊�
+		cycleTotal: function () {
+			const cycle01 = this.checkNum(this.cycle01, 0, 58)
+			const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 1, 59)
+			return cycle01 + '-' + cycle02;
+		},
+		// 璁$畻骞冲潎鐢ㄥ埌鐨勫��
+		averageTotal: function () {
+			const average01 = this.checkNum(this.average01, 0, 58)
+			const average02 = this.checkNum(this.average02, 1, 59 - average01 || 0)
+			return average01 + '/' + average02;
+		},
+		// 璁$畻鍕鹃�夌殑checkbox鍊煎悎闆�
+		checkboxString: function () {
+			let str = this.checkboxList.join();
+			return str == '' ? '*' : str;
+		}
+	}
+}
+</script>
\ No newline at end of file
diff --git a/jcdm-ui/src/components/Crontab/month.vue b/jcdm-ui/src/components/Crontab/month.vue
new file mode 100644
index 0000000..fd0ac38
--- /dev/null
+++ b/jcdm-ui/src/components/Crontab/month.vue
@@ -0,0 +1,114 @@
+<template>
+	<el-form size='small'>
+		<el-form-item>
+			<el-radio v-model='radioValue' :label="1">
+				鏈堬紝鍏佽鐨勯�氶厤绗, - * /]
+			</el-radio>
+		</el-form-item>
+
+		<el-form-item>
+			<el-radio v-model='radioValue' :label="2">
+				鍛ㄦ湡浠�
+				<el-input-number v-model='cycle01' :min="1" :max="11" /> -
+				<el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 2" :max="12" /> 鏈�
+			</el-radio>
+		</el-form-item>
+
+		<el-form-item>
+			<el-radio v-model='radioValue' :label="3">
+				浠�
+				<el-input-number v-model='average01' :min="1" :max="11" /> 鏈堝紑濮嬶紝姣�
+				<el-input-number v-model='average02' :min="1" :max="12 - average01 || 0" /> 鏈堟湀鎵ц涓�娆�
+			</el-radio>
+		</el-form-item>
+
+		<el-form-item>
+			<el-radio v-model='radioValue' :label="4">
+				鎸囧畾
+				<el-select clearable v-model="checkboxList" placeholder="鍙閫�" multiple style="width:100%">
+					<el-option v-for="item in 12" :key="item" :value="item">{{item}}</el-option>
+				</el-select>
+			</el-radio>
+		</el-form-item>
+	</el-form>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			radioValue: 1,
+			cycle01: 1,
+			cycle02: 2,
+			average01: 1,
+			average02: 1,
+			checkboxList: [],
+			checkNum: this.check
+		}
+	},
+	name: 'crontab-month',
+	props: ['check', 'cron'],
+	methods: {
+		// 鍗曢�夋寜閽�煎彉鍖栨椂
+		radioChange() {
+			switch (this.radioValue) {
+				case 1:
+					this.$emit('update', 'month', '*');
+					break;
+				case 2:
+					this.$emit('update', 'month', this.cycleTotal);
+					break;
+				case 3:
+					this.$emit('update', 'month', this.averageTotal);
+					break;
+				case 4:
+					this.$emit('update', 'month', this.checkboxString);
+					break;
+			}
+		},
+		// 鍛ㄦ湡涓や釜鍊煎彉鍖栨椂
+		cycleChange() {
+			if (this.radioValue == '2') {
+				this.$emit('update', 'month', this.cycleTotal);
+			}
+		},
+		// 骞冲潎涓や釜鍊煎彉鍖栨椂
+		averageChange() {
+			if (this.radioValue == '3') {
+				this.$emit('update', 'month', this.averageTotal);
+			}
+		},
+		// checkbox鍊煎彉鍖栨椂
+		checkboxChange() {
+			if (this.radioValue == '4') {
+				this.$emit('update', 'month', this.checkboxString);
+			}
+		}
+	},
+	watch: {
+		'radioValue': 'radioChange',
+		'cycleTotal': 'cycleChange',
+		'averageTotal': 'averageChange',
+		'checkboxString': 'checkboxChange'
+	},
+	computed: {
+		// 璁$畻涓や釜鍛ㄦ湡鍊�
+		cycleTotal: function () {
+			const cycle01 = this.checkNum(this.cycle01, 1, 11)
+			const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 2, 12)
+			return cycle01 + '-' + cycle02;
+		},
+		// 璁$畻骞冲潎鐢ㄥ埌鐨勫��
+		averageTotal: function () {
+			const average01 = this.checkNum(this.average01, 1, 11)
+			const average02 = this.checkNum(this.average02, 1, 12 - average01 || 0)
+			return average01 + '/' + average02;
+		},
+		// 璁$畻鍕鹃�夌殑checkbox鍊煎悎闆�
+		checkboxString: function () {
+			let str = this.checkboxList.join();
+			return str == '' ? '*' : str;
+		}
+	}
+}
+</script>
diff --git a/jcdm-ui/src/components/Crontab/result.vue b/jcdm-ui/src/components/Crontab/result.vue
new file mode 100644
index 0000000..aea6e0e
--- /dev/null
+++ b/jcdm-ui/src/components/Crontab/result.vue
@@ -0,0 +1,559 @@
+<template>
+	<div class="popup-result">
+		<p class="title">鏈�杩�5娆¤繍琛屾椂闂�</p>
+		<ul class="popup-result-scroll">
+			<template v-if='isShow'>
+				<li v-for='item in resultList' :key="item">{{item}}</li>
+			</template>
+			<li v-else>璁$畻缁撴灉涓�...</li>
+		</ul>
+	</div>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			dayRule: '',
+			dayRuleSup: '',
+			dateArr: [],
+			resultList: [],
+			isShow: false
+		}
+	},
+	name: 'crontab-result',
+	methods: {
+		// 琛ㄨ揪寮忓�煎彉鍖栨椂锛屽紑濮嬪幓璁$畻缁撴灉
+		expressionChange() {
+
+			// 璁$畻寮�濮�-闅愯棌缁撴灉
+			this.isShow = false;
+			// 鑾峰彇瑙勫垯鏁扮粍[0绉掋��1鍒嗐��2鏃躲��3鏃ャ��4鏈堛��5鏄熸湡銆�6骞碷
+			let ruleArr = this.$options.propsData.ex.split(' ');
+			// 鐢ㄤ簬璁板綍杩涘叆寰幆鐨勬鏁�
+			let nums = 0;
+			// 鐢ㄤ簬鏆傛椂瀛樼鍙锋椂闂磋鍒欑粨鏋滅殑鏁扮粍
+			let resultArr = [];
+			// 鑾峰彇褰撳墠鏃堕棿绮剧‘鑷砙骞淬�佹湀銆佹棩銆佹椂銆佸垎銆佺]
+			let nTime = new Date();
+			let nYear = nTime.getFullYear();
+			let nMonth = nTime.getMonth() + 1;
+			let nDay = nTime.getDate();
+			let nHour = nTime.getHours();
+			let nMin = nTime.getMinutes();
+			let nSecond = nTime.getSeconds();
+			// 鏍规嵁瑙勫垯鑾峰彇鍒拌繎100骞村彲鑳藉勾鏁扮粍銆佹湀鏁扮粍绛夌瓑
+			this.getSecondArr(ruleArr[0]);
+			this.getMinArr(ruleArr[1]);
+			this.getHourArr(ruleArr[2]);
+			this.getDayArr(ruleArr[3]);
+			this.getMonthArr(ruleArr[4]);
+			this.getWeekArr(ruleArr[5]);
+			this.getYearArr(ruleArr[6], nYear);
+			// 灏嗚幏鍙栧埌鐨勬暟缁勮祴鍊�-鏂逛究浣跨敤
+			let sDate = this.dateArr[0];
+			let mDate = this.dateArr[1];
+			let hDate = this.dateArr[2];
+			let DDate = this.dateArr[3];
+			let MDate = this.dateArr[4];
+			let YDate = this.dateArr[5];
+			// 鑾峰彇褰撳墠鏃堕棿鍦ㄦ暟缁勪腑鐨勭储寮�
+			let sIdx = this.getIndex(sDate, nSecond);
+			let mIdx = this.getIndex(mDate, nMin);
+			let hIdx = this.getIndex(hDate, nHour);
+			let DIdx = this.getIndex(DDate, nDay);
+			let MIdx = this.getIndex(MDate, nMonth);
+			let YIdx = this.getIndex(YDate, nYear);
+			// 閲嶇疆鏈堟棩鏃跺垎绉掔殑鍑芥暟(鍚庨潰鐢ㄧ殑姣旇緝澶�)
+			const resetSecond = function () {
+				sIdx = 0;
+				nSecond = sDate[sIdx]
+			}
+			const resetMin = function () {
+				mIdx = 0;
+				nMin = mDate[mIdx]
+				resetSecond();
+			}
+			const resetHour = function () {
+				hIdx = 0;
+				nHour = hDate[hIdx]
+				resetMin();
+			}
+			const resetDay = function () {
+				DIdx = 0;
+				nDay = DDate[DIdx]
+				resetHour();
+			}
+			const resetMonth = function () {
+				MIdx = 0;
+				nMonth = MDate[MIdx]
+				resetDay();
+			}
+			// 濡傛灉褰撳墠骞翠唤涓嶄负鏁扮粍涓綋鍓嶅��
+			if (nYear !== YDate[YIdx]) {
+				resetMonth();
+			}
+			// 濡傛灉褰撳墠鏈堜唤涓嶄负鏁扮粍涓綋鍓嶅��
+			if (nMonth !== MDate[MIdx]) {
+				resetDay();
+			}
+			// 濡傛灉褰撳墠鈥滄棩鈥濅笉涓烘暟缁勪腑褰撳墠鍊�
+			if (nDay !== DDate[DIdx]) {
+				resetHour();
+			}
+			// 濡傛灉褰撳墠鈥滄椂鈥濅笉涓烘暟缁勪腑褰撳墠鍊�
+			if (nHour !== hDate[hIdx]) {
+				resetMin();
+			}
+			// 濡傛灉褰撳墠鈥滃垎鈥濅笉涓烘暟缁勪腑褰撳墠鍊�
+			if (nMin !== mDate[mIdx]) {
+				resetSecond();
+			}
+
+			// 寰幆骞翠唤鏁扮粍
+			goYear: for (let Yi = YIdx; Yi < YDate.length; Yi++) {
+				let YY = YDate[Yi];
+				// 濡傛灉鍒拌揪鏈�澶у�兼椂
+				if (nMonth > MDate[MDate.length - 1]) {
+					resetMonth();
+					continue;
+				}
+				// 寰幆鏈堜唤鏁扮粍
+				goMonth: for (let Mi = MIdx; Mi < MDate.length; Mi++) {
+					// 璧嬪�笺�佹柟渚垮悗闈㈣繍绠�
+					let MM = MDate[Mi];
+					MM = MM < 10 ? '0' + MM : MM;
+					// 濡傛灉鍒拌揪鏈�澶у�兼椂
+					if (nDay > DDate[DDate.length - 1]) {
+						resetDay();
+						if (Mi == MDate.length - 1) {
+							resetMonth();
+							continue goYear;
+						}
+						continue;
+					}
+					// 寰幆鏃ユ湡鏁扮粍
+					goDay: for (let Di = DIdx; Di < DDate.length; Di++) {
+						// 璧嬪�笺�佹柟渚垮悗闈㈣繍绠�
+						let DD = DDate[Di];
+						let thisDD = DD < 10 ? '0' + DD : DD;
+
+						// 濡傛灉鍒拌揪鏈�澶у�兼椂
+						if (nHour > hDate[hDate.length - 1]) {
+							resetHour();
+							if (Di == DDate.length - 1) {
+								resetDay();
+								if (Mi == MDate.length - 1) {
+									resetMonth();
+									continue goYear;
+								}
+								continue goMonth;
+							}
+							continue;
+						}
+
+						// 鍒ゆ柇鏃ユ湡鐨勫悎娉曟�э紝涓嶅悎娉曠殑璇濅篃鏄烦鍑哄綋鍓嶅惊鐜�
+						if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true && this.dayRule !== 'workDay' && this.dayRule !== 'lastWeek' && this.dayRule !== 'lastDay') {
+							resetDay();
+							continue goMonth;
+						}
+						// 濡傛灉鏃ユ湡瑙勫垯涓湁鍊兼椂
+						if (this.dayRule == 'lastDay') {
+							// 濡傛灉涓嶆槸鍚堟硶鏃ユ湡鍒欓渶瑕佸皢鍓嶅皢鏃ユ湡璋冨埌鍚堟硶鏃ユ湡鍗虫湀鏈渶鍚庝竴澶�
+
+							if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
+								while (DD > 0 && this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
+									DD--;
+
+									thisDD = DD < 10 ? '0' + DD : DD;
+								}
+							}
+						} else if (this.dayRule == 'workDay') {
+							// 鏍¢獙骞惰皟鏁村鏋滄槸2鏈�30鍙疯繖绉嶆棩鏈熶紶杩涙潵鏃堕渶璋冩暣鑷虫甯告湀搴�
+							if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
+								while (DD > 0 && this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
+									DD--;
+									thisDD = DD < 10 ? '0' + DD : DD;
+								}
+							}
+							// 鑾峰彇杈惧埌鏉′欢鐨勬棩鏈熸槸鏄熸湡X
+							let thisWeek = this.formatDate(new Date(YY + '-' + MM + '-' + thisDD + ' 00:00:00'), 'week');
+							// 褰撴槦鏈熸棩鏃�
+							if (thisWeek == 1) {
+								// 鍏堟壘涓嬩竴涓棩锛屽苟鍒ゆ柇鏄惁涓烘湀搴�
+								DD++;
+								thisDD = DD < 10 ? '0' + DD : DD;
+								// 鍒ゆ柇涓嬩竴鏃ュ凡缁忎笉鏄悎娉曟棩鏈�
+								if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
+									DD -= 3;
+								}
+							} else if (thisWeek == 7) {
+								// 褰撴槦鏈�6鏃跺彧闇�鍒ゆ柇涓嶆槸1鍙峰氨鍙繘琛屾搷浣�
+								if (this.dayRuleSup !== 1) {
+									DD--;
+								} else {
+									DD += 2;
+								}
+							}
+						} else if (this.dayRule == 'weekDay') {
+							// 濡傛灉鎸囧畾浜嗘槸鏄熸湡鍑�
+							// 鑾峰彇褰撳墠鏃ユ湡鏄睘浜庢槦鏈熷嚑
+							let thisWeek = this.formatDate(new Date(YY + '-' + MM + '-' + DD + ' 00:00:00'), 'week');
+							// 鏍¢獙褰撳墠鏄熸湡鏄惁鍦ㄦ槦鏈熸睜锛坉ayRuleSup锛変腑
+							if (this.dayRuleSup.indexOf(thisWeek) < 0) {
+								// 濡傛灉鍒拌揪鏈�澶у�兼椂
+								if (Di == DDate.length - 1) {
+									resetDay();
+									if (Mi == MDate.length - 1) {
+										resetMonth();
+										continue goYear;
+									}
+									continue goMonth;
+								}
+								continue;
+							}
+						} else if (this.dayRule == 'assWeek') {
+							// 濡傛灉鎸囧畾浜嗘槸绗嚑鍛ㄧ殑鏄熸湡鍑�
+							// 鑾峰彇姣忔湀1鍙锋槸灞炰簬鏄熸湡鍑�
+							let thisWeek = this.formatDate(new Date(YY + '-' + MM + '-' + DD + ' 00:00:00'), 'week');
+							if (this.dayRuleSup[1] >= thisWeek) {
+								DD = (this.dayRuleSup[0] - 1) * 7 + this.dayRuleSup[1] - thisWeek + 1;
+							} else {
+								DD = this.dayRuleSup[0] * 7 + this.dayRuleSup[1] - thisWeek + 1;
+							}
+						} else if (this.dayRule == 'lastWeek') {
+							// 濡傛灉鎸囧畾浜嗘瘡鏈堟渶鍚庝竴涓槦鏈熷嚑
+							// 鏍¢獙骞惰皟鏁村鏋滄槸2鏈�30鍙疯繖绉嶆棩鏈熶紶杩涙潵鏃堕渶璋冩暣鑷虫甯告湀搴�
+							if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
+								while (DD > 0 && this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
+									DD--;
+									thisDD = DD < 10 ? '0' + DD : DD;
+								}
+							}
+							// 鑾峰彇鏈堟湯鏈�鍚庝竴澶╂槸鏄熸湡鍑�
+							let thisWeek = this.formatDate(new Date(YY + '-' + MM + '-' + thisDD + ' 00:00:00'), 'week');
+							// 鎵惧埌瑕佹眰涓渶杩戠殑閭d釜鏄熸湡鍑�
+							if (this.dayRuleSup < thisWeek) {
+								DD -= thisWeek - this.dayRuleSup;
+							} else if (this.dayRuleSup > thisWeek) {
+								DD -= 7 - (this.dayRuleSup - thisWeek)
+							}
+						}
+						// 鍒ゆ柇鏃堕棿鍊兼槸鍚﹀皬浜�10缃崲鎴愨��05鈥濊繖绉嶆牸寮�
+						DD = DD < 10 ? '0' + DD : DD;
+
+						// 寰幆鈥滄椂鈥濇暟缁�
+						goHour: for (let hi = hIdx; hi < hDate.length; hi++) {
+							let hh = hDate[hi] < 10 ? '0' + hDate[hi] : hDate[hi]
+
+							// 濡傛灉鍒拌揪鏈�澶у�兼椂
+							if (nMin > mDate[mDate.length - 1]) {
+								resetMin();
+								if (hi == hDate.length - 1) {
+									resetHour();
+									if (Di == DDate.length - 1) {
+										resetDay();
+										if (Mi == MDate.length - 1) {
+											resetMonth();
+											continue goYear;
+										}
+										continue goMonth;
+									}
+									continue goDay;
+								}
+								continue;
+							}
+							// 寰幆"鍒�"鏁扮粍
+							goMin: for (let mi = mIdx; mi < mDate.length; mi++) {
+								let mm = mDate[mi] < 10 ? '0' + mDate[mi] : mDate[mi];
+
+								// 濡傛灉鍒拌揪鏈�澶у�兼椂
+								if (nSecond > sDate[sDate.length - 1]) {
+									resetSecond();
+									if (mi == mDate.length - 1) {
+										resetMin();
+										if (hi == hDate.length - 1) {
+											resetHour();
+											if (Di == DDate.length - 1) {
+												resetDay();
+												if (Mi == MDate.length - 1) {
+													resetMonth();
+													continue goYear;
+												}
+												continue goMonth;
+											}
+											continue goDay;
+										}
+										continue goHour;
+									}
+									continue;
+								}
+								// 寰幆"绉�"鏁扮粍
+								goSecond: for (let si = sIdx; si <= sDate.length - 1; si++) {
+									let ss = sDate[si] < 10 ? '0' + sDate[si] : sDate[si];
+									// 娣诲姞褰撳墠鏃堕棿锛堟椂闂村悎娉曟�у湪鏃ユ湡寰幆鏃跺凡缁忓垽鏂級
+									if (MM !== '00' && DD !== '00') {
+										resultArr.push(YY + '-' + MM + '-' + DD + ' ' + hh + ':' + mm + ':' + ss)
+										nums++;
+									}
+									// 濡傛灉鏉℃暟婊′簡灏遍��鍑哄惊鐜�
+									if (nums == 5) break goYear;
+									// 濡傛灉鍒拌揪鏈�澶у�兼椂
+									if (si == sDate.length - 1) {
+										resetSecond();
+										if (mi == mDate.length - 1) {
+											resetMin();
+											if (hi == hDate.length - 1) {
+												resetHour();
+												if (Di == DDate.length - 1) {
+													resetDay();
+													if (Mi == MDate.length - 1) {
+														resetMonth();
+														continue goYear;
+													}
+													continue goMonth;
+												}
+												continue goDay;
+											}
+											continue goHour;
+										}
+										continue goMin;
+									}
+								} //goSecond
+							} //goMin
+						}//goHour
+					}//goDay
+				}//goMonth
+			}
+			// 鍒ゆ柇100骞村唴鐨勭粨鏋滄潯鏁�
+			if (resultArr.length == 0) {
+				this.resultList = ['娌℃湁杈惧埌鏉′欢鐨勭粨鏋滐紒'];
+			} else {
+				this.resultList = resultArr;
+				if (resultArr.length !== 5) {
+					this.resultList.push('鏈�杩�100骞村唴鍙湁涓婇潰' + resultArr.length + '鏉$粨鏋滐紒')
+				}
+			}
+			// 璁$畻瀹屾垚-鏄剧ず缁撴灉
+			this.isShow = true;
+
+
+		},
+		// 鐢ㄤ簬璁$畻鏌愪綅鏁板瓧鍦ㄦ暟缁勪腑鐨勭储寮�
+		getIndex(arr, value) {
+			if (value <= arr[0] || value > arr[arr.length - 1]) {
+				return 0;
+			} else {
+				for (let i = 0; i < arr.length - 1; i++) {
+					if (value > arr[i] && value <= arr[i + 1]) {
+						return i + 1;
+					}
+				}
+			}
+		},
+		// 鑾峰彇"骞�"鏁扮粍
+		getYearArr(rule, year) {
+			this.dateArr[5] = this.getOrderArr(year, year + 100);
+			if (rule !== undefined) {
+				if (rule.indexOf('-') >= 0) {
+					this.dateArr[5] = this.getCycleArr(rule, year + 100, false)
+				} else if (rule.indexOf('/') >= 0) {
+					this.dateArr[5] = this.getAverageArr(rule, year + 100)
+				} else if (rule !== '*') {
+					this.dateArr[5] = this.getAssignArr(rule)
+				}
+			}
+		},
+		// 鑾峰彇"鏈�"鏁扮粍
+		getMonthArr(rule) {
+			this.dateArr[4] = this.getOrderArr(1, 12);
+			if (rule.indexOf('-') >= 0) {
+				this.dateArr[4] = this.getCycleArr(rule, 12, false)
+			} else if (rule.indexOf('/') >= 0) {
+				this.dateArr[4] = this.getAverageArr(rule, 12)
+			} else if (rule !== '*') {
+				this.dateArr[4] = this.getAssignArr(rule)
+			}
+		},
+		// 鑾峰彇"鏃�"鏁扮粍-涓昏涓烘棩鏈熻鍒�
+		getWeekArr(rule) {
+			// 鍙湁褰撴棩鏈熻鍒欑殑涓や釜鍊煎潎涓衡�溾�濇椂鍒欒〃杈炬棩鏈熸槸鏈夐�夐」鐨�
+			if (this.dayRule == '' && this.dayRuleSup == '') {
+				if (rule.indexOf('-') >= 0) {
+					this.dayRule = 'weekDay';
+					this.dayRuleSup = this.getCycleArr(rule, 7, false)
+				} else if (rule.indexOf('#') >= 0) {
+					this.dayRule = 'assWeek';
+					let matchRule = rule.match(/[0-9]{1}/g);
+					this.dayRuleSup = [Number(matchRule[1]), Number(matchRule[0])];
+					this.dateArr[3] = [1];
+					if (this.dayRuleSup[1] == 7) {
+						this.dayRuleSup[1] = 0;
+					}
+				} else if (rule.indexOf('L') >= 0) {
+					this.dayRule = 'lastWeek';
+					this.dayRuleSup = Number(rule.match(/[0-9]{1,2}/g)[0]);
+					this.dateArr[3] = [31];
+					if (this.dayRuleSup == 7) {
+						this.dayRuleSup = 0;
+					}
+				} else if (rule !== '*' && rule !== '?') {
+					this.dayRule = 'weekDay';
+					this.dayRuleSup = this.getAssignArr(rule)
+				}
+			}
+		},
+		// 鑾峰彇"鏃�"鏁扮粍-灏戦噺涓烘棩鏈熻鍒�
+		getDayArr(rule) {
+			this.dateArr[3] = this.getOrderArr(1, 31);
+			this.dayRule = '';
+			this.dayRuleSup = '';
+			if (rule.indexOf('-') >= 0) {
+				this.dateArr[3] = this.getCycleArr(rule, 31, false)
+				this.dayRuleSup = 'null';
+			} else if (rule.indexOf('/') >= 0) {
+				this.dateArr[3] = this.getAverageArr(rule, 31)
+				this.dayRuleSup = 'null';
+			} else if (rule.indexOf('W') >= 0) {
+				this.dayRule = 'workDay';
+				this.dayRuleSup = Number(rule.match(/[0-9]{1,2}/g)[0]);
+				this.dateArr[3] = [this.dayRuleSup];
+			} else if (rule.indexOf('L') >= 0) {
+				this.dayRule = 'lastDay';
+				this.dayRuleSup = 'null';
+				this.dateArr[3] = [31];
+			} else if (rule !== '*' && rule !== '?') {
+				this.dateArr[3] = this.getAssignArr(rule)
+				this.dayRuleSup = 'null';
+			} else if (rule == '*') {
+				this.dayRuleSup = 'null';
+			}
+		},
+		// 鑾峰彇"鏃�"鏁扮粍
+		getHourArr(rule) {
+			this.dateArr[2] = this.getOrderArr(0, 23);
+			if (rule.indexOf('-') >= 0) {
+				this.dateArr[2] = this.getCycleArr(rule, 24, true)
+			} else if (rule.indexOf('/') >= 0) {
+				this.dateArr[2] = this.getAverageArr(rule, 23)
+			} else if (rule !== '*') {
+				this.dateArr[2] = this.getAssignArr(rule)
+			}
+		},
+		// 鑾峰彇"鍒�"鏁扮粍
+		getMinArr(rule) {
+			this.dateArr[1] = this.getOrderArr(0, 59);
+			if (rule.indexOf('-') >= 0) {
+				this.dateArr[1] = this.getCycleArr(rule, 60, true)
+			} else if (rule.indexOf('/') >= 0) {
+				this.dateArr[1] = this.getAverageArr(rule, 59)
+			} else if (rule !== '*') {
+				this.dateArr[1] = this.getAssignArr(rule)
+			}
+		},
+		// 鑾峰彇"绉�"鏁扮粍
+		getSecondArr(rule) {
+			this.dateArr[0] = this.getOrderArr(0, 59);
+			if (rule.indexOf('-') >= 0) {
+				this.dateArr[0] = this.getCycleArr(rule, 60, true)
+			} else if (rule.indexOf('/') >= 0) {
+				this.dateArr[0] = this.getAverageArr(rule, 59)
+			} else if (rule !== '*') {
+				this.dateArr[0] = this.getAssignArr(rule)
+			}
+		},
+		// 鏍规嵁浼犺繘鏉ョ殑min-max杩斿洖涓�涓『搴忕殑鏁扮粍
+		getOrderArr(min, max) {
+			let arr = [];
+			for (let i = min; i <= max; i++) {
+				arr.push(i);
+			}
+			return arr;
+		},
+		// 鏍规嵁瑙勫垯涓寚瀹氱殑闆舵暎鍊艰繑鍥炰竴涓暟缁�
+		getAssignArr(rule) {
+			let arr = [];
+			let assiginArr = rule.split(',');
+			for (let i = 0; i < assiginArr.length; i++) {
+				arr[i] = Number(assiginArr[i])
+			}
+			arr.sort(this.compare)
+			return arr;
+		},
+		// 鏍规嵁涓�瀹氱畻鏈鍒欒绠楄繑鍥炰竴涓暟缁�
+		getAverageArr(rule, limit) {
+			let arr = [];
+			let agArr = rule.split('/');
+			let min = Number(agArr[0]);
+			let step = Number(agArr[1]);
+			while (min <= limit) {
+				arr.push(min);
+				min += step;
+			}
+			return arr;
+		},
+		// 鏍规嵁瑙勫垯杩斿洖涓�涓叿鏈夊懆鏈熸�х殑鏁扮粍
+		getCycleArr(rule, limit, status) {
+			// status--琛ㄧず鏄惁浠�0寮�濮嬶紙鍒欎粠1寮�濮嬶級
+			let arr = [];
+			let cycleArr = rule.split('-');
+			let min = Number(cycleArr[0]);
+			let max = Number(cycleArr[1]);
+			if (min > max) {
+				max += limit;
+			}
+			for (let i = min; i <= max; i++) {
+				let add = 0;
+				if (status == false && i % limit == 0) {
+					add = limit;
+				}
+				arr.push(Math.round(i % limit + add))
+			}
+			arr.sort(this.compare)
+			return arr;
+		},
+		// 姣旇緝鏁板瓧澶у皬锛堢敤浜嶢rray.sort锛�
+		compare(value1, value2) {
+			if (value2 - value1 > 0) {
+				return -1;
+			} else {
+				return 1;
+			}
+		},
+		// 鏍煎紡鍖栨棩鏈熸牸寮忓锛�2017-9-19 18:04:33
+		formatDate(value, type) {
+			// 璁$畻鏃ユ湡鐩稿叧鍊�
+			let time = typeof value == 'number' ? new Date(value) : value;
+			let Y = time.getFullYear();
+			let M = time.getMonth() + 1;
+			let D = time.getDate();
+			let h = time.getHours();
+			let m = time.getMinutes();
+			let s = time.getSeconds();
+			let week = time.getDay();
+			// 濡傛灉浼犻�掍簡type鐨勮瘽
+			if (type == undefined) {
+				return Y + '-' + (M < 10 ? '0' + M : M) + '-' + (D < 10 ? '0' + D : D) + ' ' + (h < 10 ? '0' + h : h) + ':' + (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s);
+			} else if (type == 'week') {
+				// 鍦╭uartz涓� 1涓烘槦鏈熸棩
+				return week + 1;
+			}
+		},
+		// 妫�鏌ユ棩鏈熸槸鍚﹀瓨鍦�
+		checkDate(value) {
+			let time = new Date(value);
+			let format = this.formatDate(time)
+			return value === format;
+		}
+	},
+	watch: {
+		'ex': 'expressionChange'
+	},
+	props: ['ex'],
+	mounted: function () {
+		// 鍒濆鍖� 鑾峰彇涓�娆$粨鏋�
+		this.expressionChange();
+	}
+}
+
+</script>
diff --git a/jcdm-ui/src/components/Crontab/second.vue b/jcdm-ui/src/components/Crontab/second.vue
new file mode 100644
index 0000000..e7b7761
--- /dev/null
+++ b/jcdm-ui/src/components/Crontab/second.vue
@@ -0,0 +1,117 @@
+<template>
+	<el-form size="small">
+		<el-form-item>
+			<el-radio v-model='radioValue' :label="1">
+				绉掞紝鍏佽鐨勯�氶厤绗, - * /]
+			</el-radio>
+		</el-form-item>
+
+		<el-form-item>
+			<el-radio v-model='radioValue' :label="2">
+				鍛ㄦ湡浠�
+				<el-input-number v-model='cycle01' :min="0" :max="58" /> -
+				<el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 1" :max="59" /> 绉�
+			</el-radio>
+		</el-form-item>
+
+		<el-form-item>
+			<el-radio v-model='radioValue' :label="3">
+				浠�
+				<el-input-number v-model='average01' :min="0" :max="58" /> 绉掑紑濮嬶紝姣�
+				<el-input-number v-model='average02' :min="1" :max="59 - average01 || 0" /> 绉掓墽琛屼竴娆�
+			</el-radio>
+		</el-form-item>
+
+		<el-form-item>
+			<el-radio v-model='radioValue' :label="4">
+				鎸囧畾
+				<el-select clearable v-model="checkboxList" placeholder="鍙閫�" multiple style="width:100%">
+					<el-option v-for="item in 60" :key="item" :value="item-1">{{item-1}}</el-option>
+				</el-select>
+			</el-radio>
+		</el-form-item>
+	</el-form>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			radioValue: 1,
+			cycle01: 1,
+			cycle02: 2,
+			average01: 0,
+			average02: 1,
+			checkboxList: [],
+			checkNum: this.$options.propsData.check
+		}
+	},
+	name: 'crontab-second',
+	props: ['check', 'radioParent'],
+	methods: {
+		// 鍗曢�夋寜閽�煎彉鍖栨椂
+		radioChange() {
+			switch (this.radioValue) {
+				case 1:
+					this.$emit('update', 'second', '*', 'second');
+					break;
+				case 2:
+					this.$emit('update', 'second', this.cycleTotal);
+					break;
+				case 3:
+					this.$emit('update', 'second', this.averageTotal);
+					break;
+				case 4:
+					this.$emit('update', 'second', this.checkboxString);
+					break;
+			}
+		},
+		// 鍛ㄦ湡涓や釜鍊煎彉鍖栨椂
+		cycleChange() {
+			if (this.radioValue == '2') {
+				this.$emit('update', 'second', this.cycleTotal);
+			}
+		},
+		// 骞冲潎涓や釜鍊煎彉鍖栨椂
+		averageChange() {
+			if (this.radioValue == '3') {
+				this.$emit('update', 'second', this.averageTotal);
+			}
+		},
+		// checkbox鍊煎彉鍖栨椂
+		checkboxChange() {
+			if (this.radioValue == '4') {
+				this.$emit('update', 'second', this.checkboxString);
+			}
+		}
+	},
+	watch: {
+		'radioValue': 'radioChange',
+		'cycleTotal': 'cycleChange',
+		'averageTotal': 'averageChange',
+		'checkboxString': 'checkboxChange',
+		radioParent() {
+			this.radioValue = this.radioParent
+		}
+	},
+	computed: {
+		// 璁$畻涓や釜鍛ㄦ湡鍊�
+		cycleTotal: function () {
+			const cycle01 = this.checkNum(this.cycle01, 0, 58)
+			const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 1, 59)
+			return cycle01 + '-' + cycle02;
+		},
+		// 璁$畻骞冲潎鐢ㄥ埌鐨勫��
+		averageTotal: function () {
+			const average01 = this.checkNum(this.average01, 0, 58)
+			const average02 = this.checkNum(this.average02, 1, 59 - average01 || 0)
+			return average01 + '/' + average02;
+		},
+		// 璁$畻鍕鹃�夌殑checkbox鍊煎悎闆�
+		checkboxString: function () {
+			let str = this.checkboxList.join();
+			return str == '' ? '*' : str;
+		}
+	}
+}
+</script>
diff --git a/jcdm-ui/src/components/Crontab/week.vue b/jcdm-ui/src/components/Crontab/week.vue
new file mode 100644
index 0000000..1cec700
--- /dev/null
+++ b/jcdm-ui/src/components/Crontab/week.vue
@@ -0,0 +1,202 @@
+<template>
+	<el-form size='small'>
+		<el-form-item>
+			<el-radio v-model='radioValue' :label="1">
+				鍛紝鍏佽鐨勯�氶厤绗, - * ? / L #]
+			</el-radio>
+		</el-form-item>
+
+		<el-form-item>
+			<el-radio v-model='radioValue' :label="2">
+				涓嶆寚瀹�
+			</el-radio>
+		</el-form-item>
+
+		<el-form-item>
+			<el-radio v-model='radioValue' :label="3">
+				鍛ㄦ湡浠庢槦鏈�
+				<el-select clearable v-model="cycle01">
+					<el-option
+						v-for="(item,index) of weekList"
+						:key="index"
+						:label="item.value"
+						:value="item.key"
+						:disabled="item.key === 1"
+					>{{item.value}}</el-option>
+				</el-select>
+				-
+				<el-select clearable v-model="cycle02">
+					<el-option
+						v-for="(item,index) of weekList"
+						:key="index"
+						:label="item.value"
+						:value="item.key"
+						:disabled="item.key < cycle01 && item.key !== 1"
+					>{{item.value}}</el-option>
+				</el-select>
+			</el-radio>
+		</el-form-item>
+
+		<el-form-item>
+			<el-radio v-model='radioValue' :label="4">
+				绗�
+				<el-input-number v-model='average01' :min="1" :max="4" /> 鍛ㄧ殑鏄熸湡
+				<el-select clearable v-model="average02">
+					<el-option v-for="(item,index) of weekList" :key="index" :label="item.value" :value="item.key">{{item.value}}</el-option>
+				</el-select>
+			</el-radio>
+		</el-form-item>
+
+		<el-form-item>
+			<el-radio v-model='radioValue' :label="5">
+				鏈湀鏈�鍚庝竴涓槦鏈�
+				<el-select clearable v-model="weekday">
+					<el-option v-for="(item,index) of weekList" :key="index" :label="item.value" :value="item.key">{{item.value}}</el-option>
+				</el-select>
+			</el-radio>
+		</el-form-item>
+
+		<el-form-item>
+			<el-radio v-model='radioValue' :label="6">
+				鎸囧畾
+				<el-select clearable v-model="checkboxList" placeholder="鍙閫�" multiple style="width:100%">
+					<el-option v-for="(item,index) of weekList" :key="index" :label="item.value" :value="String(item.key)">{{item.value}}</el-option>
+				</el-select>
+			</el-radio>
+		</el-form-item>
+
+	</el-form>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			radioValue: 2,
+			weekday: 2,
+			cycle01: 2,
+			cycle02: 3,
+			average01: 1,
+			average02: 2,
+			checkboxList: [],
+			weekList: [
+				{
+					key: 2,
+					value: '鏄熸湡涓�'
+				},
+				{
+					key: 3,
+					value: '鏄熸湡浜�'
+				},
+				{
+					key: 4,
+					value: '鏄熸湡涓�'
+				},
+				{
+					key: 5,
+					value: '鏄熸湡鍥�'
+				},
+				{
+					key: 6,
+					value: '鏄熸湡浜�'
+				},
+				{
+					key: 7,
+					value: '鏄熸湡鍏�'
+				},
+				{
+					key: 1,
+					value: '鏄熸湡鏃�'
+				}
+			],
+			checkNum: this.$options.propsData.check
+		}
+	},
+	name: 'crontab-week',
+	props: ['check', 'cron'],
+	methods: {
+		// 鍗曢�夋寜閽�煎彉鍖栨椂
+		radioChange() {
+			if (this.radioValue !== 2 && this.cron.day !== '?') {
+				this.$emit('update', 'day', '?', 'week');
+			}
+			switch (this.radioValue) {
+				case 1:
+					this.$emit('update', 'week', '*');
+					break;
+				case 2:
+					this.$emit('update', 'week', '?');
+					break;
+				case 3:
+					this.$emit('update', 'week', this.cycleTotal);
+					break;
+				case 4:
+					this.$emit('update', 'week', this.averageTotal);
+					break;
+				case 5:
+					this.$emit('update', 'week', this.weekdayCheck + 'L');
+					break;
+				case 6:
+					this.$emit('update', 'week', this.checkboxString);
+					break;
+			}
+		},
+
+		// 鍛ㄦ湡涓や釜鍊煎彉鍖栨椂
+		cycleChange() {
+			if (this.radioValue == '3') {
+				this.$emit('update', 'week', this.cycleTotal);
+			}
+		},
+		// 骞冲潎涓や釜鍊煎彉鍖栨椂
+		averageChange() {
+			if (this.radioValue == '4') {
+				this.$emit('update', 'week', this.averageTotal);
+			}
+		},
+		// 鏈�杩戝伐浣滄棩鍊煎彉鍖栨椂
+		weekdayChange() {
+			if (this.radioValue == '5') {
+				this.$emit('update', 'week', this.weekday + 'L');
+			}
+		},
+		// checkbox鍊煎彉鍖栨椂
+		checkboxChange() {
+			if (this.radioValue == '6') {
+				this.$emit('update', 'week', this.checkboxString);
+			}
+		},
+	},
+	watch: {
+		'radioValue': 'radioChange',
+		'cycleTotal': 'cycleChange',
+		'averageTotal': 'averageChange',
+		'weekdayCheck': 'weekdayChange',
+		'checkboxString': 'checkboxChange',
+	},
+	computed: {
+		// 璁$畻涓や釜鍛ㄦ湡鍊�
+		cycleTotal: function () {
+			this.cycle01 = this.checkNum(this.cycle01, 1, 7)
+			this.cycle02 = this.checkNum(this.cycle02, 1, 7)
+			return this.cycle01 + '-' + this.cycle02;
+		},
+		// 璁$畻骞冲潎鐢ㄥ埌鐨勫��
+		averageTotal: function () {
+			this.average01 = this.checkNum(this.average01, 1, 4)
+			this.average02 = this.checkNum(this.average02, 1, 7)
+			return this.average02 + '#' + this.average01;
+		},
+		// 鏈�杩戠殑宸ヤ綔鏃ワ紙鏍煎紡锛�
+		weekdayCheck: function () {
+			this.weekday = this.checkNum(this.weekday, 1, 7)
+			return this.weekday;
+		},
+		// 璁$畻鍕鹃�夌殑checkbox鍊煎悎闆�
+		checkboxString: function () {
+			let str = this.checkboxList.join();
+			return str == '' ? '*' : str;
+		}
+	}
+}
+</script>
diff --git a/jcdm-ui/src/components/Crontab/year.vue b/jcdm-ui/src/components/Crontab/year.vue
new file mode 100644
index 0000000..5487a6c
--- /dev/null
+++ b/jcdm-ui/src/components/Crontab/year.vue
@@ -0,0 +1,131 @@
+<template>
+	<el-form size="small">
+		<el-form-item>
+			<el-radio :label="1" v-model='radioValue'>
+				涓嶅~锛屽厑璁哥殑閫氶厤绗, - * /]
+			</el-radio>
+		</el-form-item>
+
+		<el-form-item>
+			<el-radio :label="2" v-model='radioValue'>
+				姣忓勾
+			</el-radio>
+		</el-form-item>
+
+		<el-form-item>
+			<el-radio :label="3" v-model='radioValue'>
+				鍛ㄦ湡浠�
+				<el-input-number v-model='cycle01' :min='fullYear' :max="2098" /> -
+				<el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : fullYear + 1" :max="2099" />
+			</el-radio>
+		</el-form-item>
+
+		<el-form-item>
+			<el-radio :label="4" v-model='radioValue'>
+				浠�
+				<el-input-number v-model='average01' :min='fullYear' :max="2098"/> 骞村紑濮嬶紝姣�
+				<el-input-number v-model='average02' :min="1" :max="2099 - average01 || fullYear" /> 骞存墽琛屼竴娆�
+			</el-radio>
+
+		</el-form-item>
+
+		<el-form-item>
+			<el-radio :label="5" v-model='radioValue'>
+				鎸囧畾
+				<el-select clearable v-model="checkboxList" placeholder="鍙閫�" multiple>
+					<el-option v-for="item in 9" :key="item" :value="item - 1 + fullYear" :label="item -1 + fullYear" />
+				</el-select>
+			</el-radio>
+		</el-form-item>
+	</el-form>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			fullYear: 0,
+			radioValue: 1,
+			cycle01: 0,
+			cycle02: 0,
+			average01: 0,
+			average02: 1,
+			checkboxList: [],
+			checkNum: this.$options.propsData.check
+		}
+	},
+	name: 'crontab-year',
+	props: ['check', 'month', 'cron'],
+	methods: {
+		// 鍗曢�夋寜閽�煎彉鍖栨椂
+		radioChange() {
+			switch (this.radioValue) {
+				case 1:
+					this.$emit('update', 'year', '');
+					break;
+				case 2:
+					this.$emit('update', 'year', '*');
+					break;
+				case 3:
+					this.$emit('update', 'year', this.cycleTotal);
+					break;
+				case 4:
+					this.$emit('update', 'year', this.averageTotal);
+					break;
+				case 5:
+					this.$emit('update', 'year', this.checkboxString);
+					break;
+			}
+		},
+		// 鍛ㄦ湡涓や釜鍊煎彉鍖栨椂
+		cycleChange() {
+			if (this.radioValue == '3') {
+				this.$emit('update', 'year', this.cycleTotal);
+			}
+		},
+		// 骞冲潎涓や釜鍊煎彉鍖栨椂
+		averageChange() {
+			if (this.radioValue == '4') {
+				this.$emit('update', 'year', this.averageTotal);
+			}
+		},
+		// checkbox鍊煎彉鍖栨椂
+		checkboxChange() {
+			if (this.radioValue == '5') {
+				this.$emit('update', 'year', this.checkboxString);
+			}
+		}
+	},
+	watch: {
+		'radioValue': 'radioChange',
+		'cycleTotal': 'cycleChange',
+		'averageTotal': 'averageChange',
+		'checkboxString': 'checkboxChange'
+	},
+	computed: {
+		// 璁$畻涓や釜鍛ㄦ湡鍊�
+		cycleTotal: function () {
+			const cycle01 = this.checkNum(this.cycle01, this.fullYear, 2098)
+			const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : this.fullYear + 1, 2099)
+			return cycle01 + '-' + cycle02;
+		},
+		// 璁$畻骞冲潎鐢ㄥ埌鐨勫��
+		averageTotal: function () {
+			const average01 = this.checkNum(this.average01, this.fullYear, 2098)
+			const average02 = this.checkNum(this.average02, 1, 2099 - average01 || this.fullYear)
+			return average01 + '/' + average02;
+		},
+		// 璁$畻鍕鹃�夌殑checkbox鍊煎悎闆�
+		checkboxString: function () {
+			let str = this.checkboxList.join();
+			return str;
+		}
+	},
+	mounted: function () {
+		// 浠呰幏鍙栧綋鍓嶅勾浠�
+		this.fullYear = Number(new Date().getFullYear());
+		this.cycle01 = this.fullYear
+		this.average01 = this.fullYear
+	}
+}
+</script>
diff --git a/jcdm-ui/src/components/DictData/index.js b/jcdm-ui/src/components/DictData/index.js
new file mode 100644
index 0000000..7b85d4a
--- /dev/null
+++ b/jcdm-ui/src/components/DictData/index.js
@@ -0,0 +1,49 @@
+import Vue from 'vue'
+import store from '@/store'
+import DataDict from '@/utils/dict'
+import { getDicts as getDicts } from '@/api/system/dict/data'
+
+function searchDictByKey(dict, key) {
+  if (key == null && key == "") {
+    return null
+  }
+  try {
+    for (let i = 0; i < dict.length; i++) {
+      if (dict[i].key == key) {
+        return dict[i].value
+      }
+    }
+  } catch (e) {
+    return null
+  }
+}
+
+function install() {
+  Vue.use(DataDict, {
+    metas: {
+      '*': {
+        labelField: 'dictLabel',
+        valueField: 'dictValue',
+        request(dictMeta) {
+          const storeDict = searchDictByKey(store.getters.dict, dictMeta.type)
+          if (storeDict) {
+            return new Promise(resolve => { resolve(storeDict) })
+          } else {
+            return new Promise((resolve, reject) => {
+              getDicts(dictMeta.type).then(res => {
+                store.dispatch('dict/setDict', { key: dictMeta.type, value: res.data })
+                resolve(res.data)
+              }).catch(error => {
+                reject(error)
+              })
+            })
+          }
+        },
+      },
+    },
+  })
+}
+
+export default {
+  install,
+}
\ No newline at end of file
diff --git a/jcdm-ui/src/components/DictTag/index.vue b/jcdm-ui/src/components/DictTag/index.vue
new file mode 100644
index 0000000..6b5b230
--- /dev/null
+++ b/jcdm-ui/src/components/DictTag/index.vue
@@ -0,0 +1,89 @@
+<template>
+  <div>
+    <template v-for="(item, index) in options">
+      <template v-if="values.includes(item.value)">
+        <span
+          v-if="(item.raw.listClass == 'default' || item.raw.listClass == '') && (item.raw.cssClass == '' || item.raw.cssClass == null)"
+          :key="item.value"
+          :index="index"
+          :class="item.raw.cssClass"
+          >{{ item.label + ' ' }}</span
+        >
+        <el-tag
+          v-else
+          :disable-transitions="true"
+          :key="item.value"
+          :index="index"
+          :type="item.raw.listClass == 'primary' ? '' : item.raw.listClass"
+          :class="item.raw.cssClass"
+        >
+          {{ item.label + ' ' }}
+        </el-tag>
+      </template>
+    </template>
+    <template v-if="unmatch && showValue">
+      {{ unmatchArray | handleArray }}
+    </template>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "DictTag",
+  props: {
+    options: {
+      type: Array,
+      default: null,
+    },
+    value: [Number, String, Array],
+    // 褰撴湭鎵惧埌鍖归厤鐨勬暟鎹椂锛屾樉绀簐alue
+    showValue: {
+      type: Boolean,
+      default: true,
+    },
+    separator: {
+      type: String,
+      default: ","
+    }
+  },
+  data() {
+    return {
+      unmatchArray: [], // 璁板綍鏈尮閰嶇殑椤�
+    }
+  },
+  computed: {
+    values() {
+      if (this.value === null || typeof this.value === 'undefined' || this.value === '') return []
+      return Array.isArray(this.value) ? this.value.map(item => '' + item) : String(this.value).split(this.separator)
+    },
+    unmatch() {
+      this.unmatchArray = []
+      // 娌℃湁value涓嶆樉绀�
+      if (this.value === null || typeof this.value === 'undefined' || this.value === '' || this.options.length === 0) return false
+      // 浼犲叆鍊间负鏁扮粍
+      let unmatch = false // 娣诲姞涓�涓爣蹇楁潵鍒ゆ柇鏄惁鏈夋湭鍖归厤椤�
+      this.values.forEach(item => {
+        if (!this.options.some(v => v.value === item)) {
+          this.unmatchArray.push(item)
+          unmatch = true // 濡傛灉鏈夋湭鍖归厤椤癸紝灏嗘爣蹇楄缃负true
+        }
+      })
+      return unmatch // 杩斿洖鏍囧織鐨勫��
+    },
+
+  },
+  filters: {
+    handleArray(array) {
+      if (array.length === 0) return '';
+      return array.reduce((pre, cur) => {
+        return pre + ' ' + cur;
+      })
+    },
+  }
+};
+</script>
+<style scoped>
+.el-tag + .el-tag {
+  margin-left: 10px;
+}
+</style>
diff --git a/jcdm-ui/src/components/Editor/index.vue b/jcdm-ui/src/components/Editor/index.vue
new file mode 100644
index 0000000..8981d76
--- /dev/null
+++ b/jcdm-ui/src/components/Editor/index.vue
@@ -0,0 +1,274 @@
+<template>
+  <div>
+    <el-upload
+      :action="uploadUrl"
+      :before-upload="handleBeforeUpload"
+      :on-success="handleUploadSuccess"
+      :on-error="handleUploadError"
+      name="file"
+      :show-file-list="false"
+      :headers="headers"
+      style="display: none"
+      ref="upload"
+      v-if="this.type == 'url'"
+    >
+    </el-upload>
+    <div class="editor" ref="editor" :style="styles"></div>
+  </div>
+</template>
+
+<script>
+import Quill from "quill";
+import "quill/dist/quill.core.css";
+import "quill/dist/quill.snow.css";
+import "quill/dist/quill.bubble.css";
+import { getToken } from "@/utils/auth";
+
+export default {
+  name: "Editor",
+  props: {
+    /* 缂栬緫鍣ㄧ殑鍐呭 */
+    value: {
+      type: String,
+      default: "",
+    },
+    /* 楂樺害 */
+    height: {
+      type: Number,
+      default: null,
+    },
+    /* 鏈�灏忛珮搴� */
+    minHeight: {
+      type: Number,
+      default: null,
+    },
+    /* 鍙 */
+    readOnly: {
+      type: Boolean,
+      default: false,
+    },
+    /* 涓婁紶鏂囦欢澶у皬闄愬埗(MB) */
+    fileSize: {
+      type: Number,
+      default: 5,
+    },
+    /* 绫诲瀷锛坆ase64鏍煎紡銆乽rl鏍煎紡锛� */
+    type: {
+      type: String,
+      default: "url",
+    }
+  },
+  data() {
+    return {
+      uploadUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 涓婁紶鐨勫浘鐗囨湇鍔″櫒鍦板潃
+      headers: {
+        Authorization: "Bearer " + getToken()
+      },
+      Quill: null,
+      currentValue: "",
+      options: {
+        theme: "snow",
+        bounds: document.body,
+        debug: "warn",
+        modules: {
+          // 宸ュ叿鏍忛厤缃�
+          toolbar: [
+            ["bold", "italic", "underline", "strike"],       // 鍔犵矖 鏂滀綋 涓嬪垝绾� 鍒犻櫎绾�
+            ["blockquote", "code-block"],                    // 寮曠敤  浠g爜鍧�
+            [{ list: "ordered" }, { list: "bullet" }],       // 鏈夊簭銆佹棤搴忓垪琛�
+            [{ indent: "-1" }, { indent: "+1" }],            // 缂╄繘
+            [{ size: ["small", false, "large", "huge"] }],   // 瀛椾綋澶у皬
+            [{ header: [1, 2, 3, 4, 5, 6, false] }],         // 鏍囬
+            [{ color: [] }, { background: [] }],             // 瀛椾綋棰滆壊銆佸瓧浣撹儗鏅鑹�
+            [{ align: [] }],                                 // 瀵归綈鏂瑰紡
+            ["clean"],                                       // 娓呴櫎鏂囨湰鏍煎紡
+            ["link", "image", "video"]                       // 閾炬帴銆佸浘鐗囥�佽棰�
+          ],
+        },
+        placeholder: "璇疯緭鍏ュ唴瀹�",
+        readOnly: this.readOnly,
+      },
+    };
+  },
+  computed: {
+    styles() {
+      let style = {};
+      if (this.minHeight) {
+        style.minHeight = `${this.minHeight}px`;
+      }
+      if (this.height) {
+        style.height = `${this.height}px`;
+      }
+      return style;
+    },
+  },
+  watch: {
+    value: {
+      handler(val) {
+        if (val !== this.currentValue) {
+          this.currentValue = val === null ? "" : val;
+          if (this.Quill) {
+            this.Quill.pasteHTML(this.currentValue);
+          }
+        }
+      },
+      immediate: true,
+    },
+  },
+  mounted() {
+    this.init();
+  },
+  beforeDestroy() {
+    this.Quill = null;
+  },
+  methods: {
+    init() {
+      const editor = this.$refs.editor;
+      this.Quill = new Quill(editor, this.options);
+      // 濡傛灉璁剧疆浜嗕笂浼犲湴鍧�鍒欒嚜瀹氫箟鍥剧墖涓婁紶浜嬩欢
+      if (this.type == 'url') {
+        let toolbar = this.Quill.getModule("toolbar");
+        toolbar.addHandler("image", (value) => {
+          if (value) {
+            this.$refs.upload.$children[0].$refs.input.click();
+          } else {
+            this.quill.format("image", false);
+          }
+        });
+      }
+      this.Quill.pasteHTML(this.currentValue);
+      this.Quill.on("text-change", (delta, oldDelta, source) => {
+        const html = this.$refs.editor.children[0].innerHTML;
+        const text = this.Quill.getText();
+        const quill = this.Quill;
+        this.currentValue = html;
+        this.$emit("input", html);
+        this.$emit("on-change", { html, text, quill });
+      });
+      this.Quill.on("text-change", (delta, oldDelta, source) => {
+        this.$emit("on-text-change", delta, oldDelta, source);
+      });
+      this.Quill.on("selection-change", (range, oldRange, source) => {
+        this.$emit("on-selection-change", range, oldRange, source);
+      });
+      this.Quill.on("editor-change", (eventName, ...args) => {
+        this.$emit("on-editor-change", eventName, ...args);
+      });
+    },
+    // 涓婁紶鍓嶆牎妫�鏍煎紡鍜屽ぇ灏�
+    handleBeforeUpload(file) {
+      const type = ["image/jpeg", "image/jpg", "image/png", "image/svg"];
+      const isJPG = type.includes(file.type);
+      // 妫�楠屾枃浠舵牸寮�
+      if (!isJPG) {
+        this.$message.error(`鍥剧墖鏍煎紡閿欒!`);
+        return false;
+      }
+      // 鏍℃鏂囦欢澶у皬
+      if (this.fileSize) {
+        const isLt = file.size / 1024 / 1024 < this.fileSize;
+        if (!isLt) {
+          this.$message.error(`涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃 ${this.fileSize} MB!`);
+          return false;
+        }
+      }
+      return true;
+    },
+    handleUploadSuccess(res, file) {
+      // 濡傛灉涓婁紶鎴愬姛
+      if (res.code == 200) {
+        // 鑾峰彇瀵屾枃鏈粍浠跺疄渚�
+        let quill = this.Quill;
+        // 鑾峰彇鍏夋爣鎵�鍦ㄤ綅缃�
+        let length = quill.getSelection().index;
+        // 鎻掑叆鍥剧墖  res.url涓烘湇鍔″櫒杩斿洖鐨勫浘鐗囧湴鍧�
+        quill.insertEmbed(length, "image", process.env.VUE_APP_BASE_API + res.fileName);
+        // 璋冩暣鍏夋爣鍒版渶鍚�
+        quill.setSelection(length + 1);
+      } else {
+        this.$message.error("鍥剧墖鎻掑叆澶辫触");
+      }
+    },
+    handleUploadError() {
+      this.$message.error("鍥剧墖鎻掑叆澶辫触");
+    },
+  },
+};
+</script>
+
+<style>
+.editor, .ql-toolbar {
+  white-space: pre-wrap !important;
+  line-height: normal !important;
+}
+.quill-img {
+  display: none;
+}
+.ql-snow .ql-tooltip[data-mode="link"]::before {
+  content: "璇疯緭鍏ラ摼鎺ュ湴鍧�:";
+}
+.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
+  border-right: 0px;
+  content: "淇濆瓨";
+  padding-right: 0px;
+}
+.ql-snow .ql-tooltip[data-mode="video"]::before {
+  content: "璇疯緭鍏ヨ棰戝湴鍧�:";
+}
+.ql-snow .ql-picker.ql-size .ql-picker-label::before,
+.ql-snow .ql-picker.ql-size .ql-picker-item::before {
+  content: "14px";
+}
+.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
+.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
+  content: "10px";
+}
+.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
+.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
+  content: "18px";
+}
+.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
+.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
+  content: "32px";
+}
+.ql-snow .ql-picker.ql-header .ql-picker-label::before,
+.ql-snow .ql-picker.ql-header .ql-picker-item::before {
+  content: "鏂囨湰";
+}
+.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
+.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
+  content: "鏍囬1";
+}
+.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
+.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
+  content: "鏍囬2";
+}
+.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
+.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
+  content: "鏍囬3";
+}
+.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
+.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
+  content: "鏍囬4";
+}
+.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
+.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
+  content: "鏍囬5";
+}
+.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
+.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
+  content: "鏍囬6";
+}
+.ql-snow .ql-picker.ql-font .ql-picker-label::before,
+.ql-snow .ql-picker.ql-font .ql-picker-item::before {
+  content: "鏍囧噯瀛椾綋";
+}
+.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before,
+.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
+  content: "琛嚎瀛椾綋";
+}
+.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before,
+.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {
+  content: "绛夊瀛椾綋";
+}
+</style>
diff --git a/jcdm-ui/src/components/FileUpload/index.vue b/jcdm-ui/src/components/FileUpload/index.vue
new file mode 100644
index 0000000..c7f6b0a
--- /dev/null
+++ b/jcdm-ui/src/components/FileUpload/index.vue
@@ -0,0 +1,216 @@
+<template>
+  <div class="upload-file">
+    <el-upload
+      multiple
+      :action="uploadFileUrl"
+      :before-upload="handleBeforeUpload"
+      :file-list="fileList"
+      :limit="limit"
+      :on-error="handleUploadError"
+      :on-exceed="handleExceed"
+      :on-success="handleUploadSuccess"
+      :show-file-list="false"
+      :headers="headers"
+      class="upload-file-uploader"
+      ref="fileUpload"
+    >
+      <!-- 涓婁紶鎸夐挳 -->
+      <el-button size="mini" type="primary">閫夊彇鏂囦欢</el-button>
+      <!-- 涓婁紶鎻愮ず -->
+      <div class="el-upload__tip" slot="tip" v-if="showTip">
+        璇蜂笂浼�
+        <template v-if="fileSize"> 澶у皬涓嶈秴杩� <b style="color: #f56c6c">{{ fileSize }}MB</b> </template>
+        <template v-if="fileType"> 鏍煎紡涓� <b style="color: #f56c6c">{{ fileType.join("/") }}</b> </template>
+        鐨勬枃浠�
+      </div>
+    </el-upload>
+
+    <!-- 鏂囦欢鍒楄〃 -->
+    <transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul">
+      <li :key="file.url" class="el-upload-list__item ele-upload-list__item-content" v-for="(file, index) in fileList">
+        <el-link :href="`${baseUrl}${file.url}`" :underline="false" target="_blank">
+          <span class="el-icon-document"> {{ getFileName(file.name) }} </span>
+        </el-link>
+        <div class="ele-upload-list__item-content-action">
+          <el-link :underline="false" @click="handleDelete(index)" type="danger">鍒犻櫎</el-link>
+        </div>
+      </li>
+    </transition-group>
+  </div>
+</template>
+
+<script>
+import { getToken } from "@/utils/auth";
+
+export default {
+  name: "FileUpload",
+  props: {
+    // 鍊�
+    value: [String, Object, Array],
+    // 鏁伴噺闄愬埗
+    limit: {
+      type: Number,
+      default: 5,
+    },
+    // 澶у皬闄愬埗(MB)
+    fileSize: {
+      type: Number,
+      default: 5,
+    },
+    // 鏂囦欢绫诲瀷, 渚嬪['png', 'jpg', 'jpeg']
+    fileType: {
+      type: Array,
+      default: () => ["doc", "xls", "ppt", "txt", "pdf"],
+    },
+    // 鏄惁鏄剧ず鎻愮ず
+    isShowTip: {
+      type: Boolean,
+      default: true
+    }
+  },
+  data() {
+    return {
+      number: 0,
+      uploadList: [],
+      baseUrl: process.env.VUE_APP_BASE_API,
+      uploadFileUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 涓婁紶鏂囦欢鏈嶅姟鍣ㄥ湴鍧�
+      headers: {
+        Authorization: "Bearer " + getToken(),
+      },
+      fileList: [],
+    };
+  },
+  watch: {
+    value: {
+      handler(val) {
+        if (val) {
+          let temp = 1;
+          // 棣栧厛灏嗗�艰浆涓烘暟缁�
+          const list = Array.isArray(val) ? val : this.value.split(',');
+          // 鐒跺悗灏嗘暟缁勮浆涓哄璞℃暟缁�
+          this.fileList = list.map(item => {
+            if (typeof item === "string") {
+              item = { name: item, url: item };
+            }
+            item.uid = item.uid || new Date().getTime() + temp++;
+            return item;
+          });
+        } else {
+          this.fileList = [];
+          return [];
+        }
+      },
+      deep: true,
+      immediate: true
+    }
+  },
+  computed: {
+    // 鏄惁鏄剧ず鎻愮ず
+    showTip() {
+      return this.isShowTip && (this.fileType || this.fileSize);
+    },
+  },
+  methods: {
+    // 涓婁紶鍓嶆牎妫�鏍煎紡鍜屽ぇ灏�
+    handleBeforeUpload(file) {
+      // 鏍℃鏂囦欢绫诲瀷
+      if (this.fileType) {
+        const fileName = file.name.split('.');
+        const fileExt = fileName[fileName.length - 1];
+        const isTypeOk = this.fileType.indexOf(fileExt) >= 0;
+        if (!isTypeOk) {
+          this.$modal.msgError(`鏂囦欢鏍煎紡涓嶆纭�, 璇蜂笂浼�${this.fileType.join("/")}鏍煎紡鏂囦欢!`);
+          return false;
+        }
+      }
+      // 鏍℃鏂囦欢澶у皬
+      if (this.fileSize) {
+        const isLt = file.size / 1024 / 1024 < this.fileSize;
+        if (!isLt) {
+          this.$modal.msgError(`涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃 ${this.fileSize} MB!`);
+          return false;
+        }
+      }
+      this.$modal.loading("姝e湪涓婁紶鏂囦欢锛岃绋嶅��...");
+      this.number++;
+      return true;
+    },
+    // 鏂囦欢涓暟瓒呭嚭
+    handleExceed() {
+      this.$modal.msgError(`涓婁紶鏂囦欢鏁伴噺涓嶈兘瓒呰繃 ${this.limit} 涓�!`);
+    },
+    // 涓婁紶澶辫触
+    handleUploadError(err) {
+      this.$modal.msgError("涓婁紶鏂囦欢澶辫触锛岃閲嶈瘯");
+      this.$modal.closeLoading();
+    },
+    // 涓婁紶鎴愬姛鍥炶皟
+    handleUploadSuccess(res, file) {
+      if (res.code === 200) {
+        this.uploadList.push({ name: res.fileName, url: res.fileName });
+        this.uploadedSuccessfully();
+      } else {
+        this.number--;
+        this.$modal.closeLoading();
+        this.$modal.msgError(res.msg);
+        this.$refs.fileUpload.handleRemove(file);
+        this.uploadedSuccessfully();
+      }
+    },
+    // 鍒犻櫎鏂囦欢
+    handleDelete(index) {
+      this.fileList.splice(index, 1);
+      this.$emit("input", this.listToString(this.fileList));
+    },
+    // 涓婁紶缁撴潫澶勭悊
+    uploadedSuccessfully() {
+      if (this.number > 0 && this.uploadList.length === this.number) {
+        this.fileList = this.fileList.concat(this.uploadList);
+        this.uploadList = [];
+        this.number = 0;
+        this.$emit("input", this.listToString(this.fileList));
+        this.$modal.closeLoading();
+      }
+    },
+    // 鑾峰彇鏂囦欢鍚嶇О
+    getFileName(name) {
+      // 濡傛灉鏄痷rl閭d箞鍙栨渶鍚庣殑鍚嶅瓧 濡傛灉涓嶆槸鐩存帴杩斿洖
+      if (name.lastIndexOf("/") > -1) {
+        return name.slice(name.lastIndexOf("/") + 1);
+      } else {
+        return name;
+      }
+    },
+    // 瀵硅薄杞垚鎸囧畾瀛楃涓插垎闅�
+    listToString(list, separator) {
+      let strs = "";
+      separator = separator || ",";
+      for (let i in list) {
+        strs += list[i].url + separator;
+      }
+      return strs != '' ? strs.substr(0, strs.length - 1) : '';
+    }
+  }
+};
+</script>
+
+<style scoped lang="scss">
+.upload-file-uploader {
+  margin-bottom: 5px;
+}
+.upload-file-list .el-upload-list__item {
+  border: 1px solid #e4e7ed;
+  line-height: 2;
+  margin-bottom: 10px;
+  position: relative;
+}
+.upload-file-list .ele-upload-list__item-content {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  color: inherit;
+}
+.ele-upload-list__item-content-action .el-link {
+  margin-right: 10px;
+}
+</style>
diff --git a/jcdm-ui/src/components/Hamburger/index.vue b/jcdm-ui/src/components/Hamburger/index.vue
new file mode 100644
index 0000000..368b002
--- /dev/null
+++ b/jcdm-ui/src/components/Hamburger/index.vue
@@ -0,0 +1,44 @@
+<template>
+  <div style="padding: 0 15px;" @click="toggleClick">
+    <svg
+      :class="{'is-active':isActive}"
+      class="hamburger"
+      viewBox="0 0 1024 1024"
+      xmlns="http://www.w3.org/2000/svg"
+      width="64"
+      height="64"
+    >
+      <path d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z" />
+    </svg>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'Hamburger',
+  props: {
+    isActive: {
+      type: Boolean,
+      default: false
+    }
+  },
+  methods: {
+    toggleClick() {
+      this.$emit('toggleClick')
+    }
+  }
+}
+</script>
+
+<style scoped>
+.hamburger {
+  display: inline-block;
+  vertical-align: middle;
+  width: 20px;
+  height: 20px;
+}
+
+.hamburger.is-active {
+  transform: rotate(180deg);
+}
+</style>
diff --git a/jcdm-ui/src/components/HeaderSearch/index.vue b/jcdm-ui/src/components/HeaderSearch/index.vue
new file mode 100644
index 0000000..7d6780b
--- /dev/null
+++ b/jcdm-ui/src/components/HeaderSearch/index.vue
@@ -0,0 +1,198 @@
+<template>
+  <div :class="{'show':show}" class="header-search">
+    <svg-icon class-name="search-icon" icon-class="search" @click.stop="click" />
+    <el-select
+      ref="headerSearchSelect"
+      v-model="search"
+      :remote-method="querySearch"
+      filterable
+      default-first-option
+      remote
+      placeholder="Search"
+      class="header-search-select"
+      @change="change"
+    >
+      <el-option v-for="option in options" :key="option.item.path" :value="option.item" :label="option.item.title.join(' > ')" />
+    </el-select>
+  </div>
+</template>
+
+<script>
+// fuse is a lightweight fuzzy-search module
+// make search results more in line with expectations
+import Fuse from 'fuse.js/dist/fuse.min.js'
+import path from 'path'
+
+export default {
+  name: 'HeaderSearch',
+  data() {
+    return {
+      search: '',
+      options: [],
+      searchPool: [],
+      show: false,
+      fuse: undefined
+    }
+  },
+  computed: {
+    routes() {
+      return this.$store.getters.permission_routes
+    }
+  },
+  watch: {
+    routes() {
+      this.searchPool = this.generateRoutes(this.routes)
+    },
+    searchPool(list) {
+      this.initFuse(list)
+    },
+    show(value) {
+      if (value) {
+        document.body.addEventListener('click', this.close)
+      } else {
+        document.body.removeEventListener('click', this.close)
+      }
+    }
+  },
+  mounted() {
+    this.searchPool = this.generateRoutes(this.routes)
+  },
+  methods: {
+    click() {
+      this.show = !this.show
+      if (this.show) {
+        this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.focus()
+      }
+    },
+    close() {
+      this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.blur()
+      this.options = []
+      this.show = false
+    },
+    change(val) {
+      const path = val.path;
+      const query = val.query;
+      if(this.ishttp(val.path)) {
+        // http(s):// 璺緞鏂扮獥鍙f墦寮�
+        const pindex = path.indexOf("http");
+        window.open(path.substr(pindex, path.length), "_blank");
+      } else {
+        if (query) {
+          this.$router.push({ path: path, query: JSON.parse(query) });
+        } else {
+          this.$router.push(path)
+        }
+      }
+      this.search = ''
+      this.options = []
+      this.$nextTick(() => {
+        this.show = false
+      })
+    },
+    initFuse(list) {
+      this.fuse = new Fuse(list, {
+        shouldSort: true,
+        threshold: 0.4,
+        location: 0,
+        distance: 100,
+        minMatchCharLength: 1,
+        keys: [{
+          name: 'title',
+          weight: 0.7
+        }, {
+          name: 'path',
+          weight: 0.3
+        }]
+      })
+    },
+    // Filter out the routes that can be displayed in the sidebar
+    // And generate the internationalized title
+    generateRoutes(routes, basePath = '/', prefixTitle = []) {
+      let res = []
+
+      for (const router of routes) {
+        // skip hidden router
+        if (router.hidden) { continue }
+
+        const data = {
+          path: !this.ishttp(router.path) ? path.resolve(basePath, router.path) : router.path,
+          title: [...prefixTitle]
+        }
+
+        if (router.meta && router.meta.title) {
+          data.title = [...data.title, router.meta.title]
+
+          if (router.redirect !== 'noRedirect') {
+            // only push the routes with title
+            // special case: need to exclude parent router without redirect
+            res.push(data)
+          }
+        }
+
+        if (router.query) {
+          data.query = router.query
+        }
+
+        // recursive child routes
+        if (router.children) {
+          const tempRoutes = this.generateRoutes(router.children, data.path, data.title)
+          if (tempRoutes.length >= 1) {
+            res = [...res, ...tempRoutes]
+          }
+        }
+      }
+      return res
+    },
+    querySearch(query) {
+      if (query !== '') {
+        this.options = this.fuse.search(query)
+      } else {
+        this.options = []
+      }
+    },
+    ishttp(url) {
+      return url.indexOf('http://') !== -1 || url.indexOf('https://') !== -1
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.header-search {
+  font-size: 0 !important;
+
+  .search-icon {
+    cursor: pointer;
+    font-size: 18px;
+    vertical-align: middle;
+  }
+
+  .header-search-select {
+    font-size: 18px;
+    transition: width 0.2s;
+    width: 0;
+    overflow: hidden;
+    background: transparent;
+    border-radius: 0;
+    display: inline-block;
+    vertical-align: middle;
+
+    ::v-deep .el-input__inner {
+      border-radius: 0;
+      border: 0;
+      padding-left: 0;
+      padding-right: 0;
+      box-shadow: none !important;
+      border-bottom: 1px solid #d9d9d9;
+      vertical-align: middle;
+    }
+  }
+
+  &.show {
+    .header-search-select {
+      width: 210px;
+      margin-left: 10px;
+    }
+  }
+}
+</style>
diff --git a/jcdm-ui/src/components/IconSelect/index.vue b/jcdm-ui/src/components/IconSelect/index.vue
new file mode 100644
index 0000000..8dadc02
--- /dev/null
+++ b/jcdm-ui/src/components/IconSelect/index.vue
@@ -0,0 +1,104 @@
+<!-- @author zhengjie -->
+<template>
+  <div class="icon-body">
+    <el-input v-model="name" class="icon-search" clearable placeholder="璇疯緭鍏ュ浘鏍囧悕绉�" @clear="filterIcons" @input="filterIcons">
+      <i slot="suffix" class="el-icon-search el-input__icon" />
+    </el-input>
+    <div class="icon-list">
+      <div class="list-container">
+        <div v-for="(item, index) in iconList" class="icon-item-wrapper" :key="index" @click="selectedIcon(item)">
+          <div :class="['icon-item', { active: activeIcon === item }]">
+            <svg-icon :icon-class="item" class-name="icon" style="height: 25px;width: 16px;"/>
+            <span>{{ item }}</span>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import icons from './requireIcons'
+export default {
+  name: 'IconSelect',
+  props: {
+    activeIcon: {
+      type: String
+    }
+  },
+  data() {
+    return {
+      name: '',
+      iconList: icons
+    }
+  },
+  methods: {
+    filterIcons() {
+      this.iconList = icons
+      if (this.name) {
+        this.iconList = this.iconList.filter(item => item.includes(this.name))
+      }
+    },
+    selectedIcon(name) {
+      this.$emit('selected', name)
+      document.body.click()
+    },
+    reset() {
+      this.name = ''
+      this.iconList = icons
+    }
+  }
+}
+</script>
+
+<style rel="stylesheet/scss" lang="scss" scoped>
+  .icon-body {
+    width: 100%;
+    padding: 10px;
+    .icon-search {
+      position: relative;
+      margin-bottom: 5px;
+    }
+    .icon-list {
+      height: 200px;
+      overflow: auto;
+      .list-container {
+        display: flex;
+        flex-wrap: wrap;
+        .icon-item-wrapper {
+          width: calc(100% / 3);
+          height: 25px;
+          line-height: 25px;
+          cursor: pointer;
+          display: flex;
+          .icon-item {
+            display: flex;
+            max-width: 100%;
+            height: 100%;
+            padding: 0 5px;
+            &:hover {
+              background: #ececec;
+              border-radius: 5px;
+            }
+            .icon {
+              flex-shrink: 0;
+            }
+            span {
+              display: inline-block;
+              vertical-align: -0.15em;
+              fill: currentColor;
+              padding-left: 2px;
+              overflow: hidden;
+              text-overflow: ellipsis;
+              white-space: nowrap;
+            }
+          }
+          .icon-item.active {
+            background: #ececec;
+            border-radius: 5px;
+          }
+        }
+      }
+    }
+  }
+</style>
diff --git a/jcdm-ui/src/components/IconSelect/requireIcons.js b/jcdm-ui/src/components/IconSelect/requireIcons.js
new file mode 100644
index 0000000..99e5c54
--- /dev/null
+++ b/jcdm-ui/src/components/IconSelect/requireIcons.js
@@ -0,0 +1,11 @@
+
+const req = require.context('../../assets/icons/svg', false, /\.svg$/)
+const requireAll = requireContext => requireContext.keys()
+
+const re = /\.\/(.*)\.svg/
+
+const icons = requireAll(req).map(i => {
+  return i.match(re)[1]
+})
+
+export default icons
diff --git a/jcdm-ui/src/components/ImagePreview/index.vue b/jcdm-ui/src/components/ImagePreview/index.vue
new file mode 100644
index 0000000..3c770c7
--- /dev/null
+++ b/jcdm-ui/src/components/ImagePreview/index.vue
@@ -0,0 +1,90 @@
+<template>
+  <el-image
+    :src="`${realSrc}`"
+    fit="cover"
+    :style="`width:${realWidth};height:${realHeight};`"
+    :preview-src-list="realSrcList"
+  >
+    <div slot="error" class="image-slot">
+      <i class="el-icon-picture-outline"></i>
+    </div>
+  </el-image>
+</template>
+
+<script>
+import { isExternal } from "@/utils/validate";
+
+export default {
+  name: "ImagePreview",
+  props: {
+    src: {
+      type: String,
+      default: ""
+    },
+    width: {
+      type: [Number, String],
+      default: ""
+    },
+    height: {
+      type: [Number, String],
+      default: ""
+    }
+  },
+  computed: {
+    realSrc() {
+      if (!this.src) {
+        return;
+      }
+      let real_src = this.src.split(",")[0];
+      if (isExternal(real_src)) {
+        return real_src;
+      }
+      return process.env.VUE_APP_BASE_API + real_src;
+    },
+    realSrcList() {
+      if (!this.src) {
+        return;
+      }
+      let real_src_list = this.src.split(",");
+      let srcList = [];
+      real_src_list.forEach(item => {
+        if (isExternal(item)) {
+          return srcList.push(item);
+        }
+        return srcList.push(process.env.VUE_APP_BASE_API + item);
+      });
+      return srcList;
+    },
+    realWidth() {
+      return typeof this.width == "string" ? this.width : `${this.width}px`;
+    },
+    realHeight() {
+      return typeof this.height == "string" ? this.height : `${this.height}px`;
+    }
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.el-image {
+  border-radius: 5px;
+  background-color: #ebeef5;
+  box-shadow: 0 0 5px 1px #ccc;
+  ::v-deep .el-image__inner {
+    transition: all 0.3s;
+    cursor: pointer;
+    &:hover {
+      transform: scale(1.2);
+    }
+  }
+  ::v-deep .image-slot {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    width: 100%;
+    height: 100%;
+    color: #909399;
+    font-size: 30px;
+  }
+}
+</style>
diff --git a/jcdm-ui/src/components/ImageUpload/index.vue b/jcdm-ui/src/components/ImageUpload/index.vue
new file mode 100644
index 0000000..2e64c9b
--- /dev/null
+++ b/jcdm-ui/src/components/ImageUpload/index.vue
@@ -0,0 +1,226 @@
+<template>
+  <div class="component-upload-image">
+    <el-upload
+      multiple
+      :action="uploadImgUrl"
+      list-type="picture-card"
+      :on-success="handleUploadSuccess"
+      :before-upload="handleBeforeUpload"
+      :limit="limit"
+      :on-error="handleUploadError"
+      :on-exceed="handleExceed"
+      ref="imageUpload"
+      :on-remove="handleDelete"
+      :show-file-list="true"
+      :headers="headers"
+      :file-list="fileList"
+      :on-preview="handlePictureCardPreview"
+      :class="{hide: this.fileList.length >= this.limit}"
+    >
+      <i class="el-icon-plus"></i>
+    </el-upload>
+
+    <!-- 涓婁紶鎻愮ず -->
+    <div class="el-upload__tip" slot="tip" v-if="showTip">
+      璇蜂笂浼�
+      <template v-if="fileSize"> 澶у皬涓嶈秴杩� <b style="color: #f56c6c">{{ fileSize }}MB</b> </template>
+      <template v-if="fileType"> 鏍煎紡涓� <b style="color: #f56c6c">{{ fileType.join("/") }}</b> </template>
+      鐨勬枃浠�
+    </div>
+
+    <el-dialog
+      :visible.sync="dialogVisible"
+      title="棰勮"
+      width="800"
+      append-to-body
+    >
+      <img
+        :src="dialogImageUrl"
+        style="display: block; max-width: 100%; margin: 0 auto"
+      />
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { getToken } from "@/utils/auth";
+
+export default {
+  props: {
+    value: [String, Object, Array],
+    // 鍥剧墖鏁伴噺闄愬埗
+    limit: {
+      type: Number,
+      default: 5,
+    },
+    // 澶у皬闄愬埗(MB)
+    fileSize: {
+       type: Number,
+      default: 5,
+    },
+    // 鏂囦欢绫诲瀷, 渚嬪['png', 'jpg', 'jpeg']
+    fileType: {
+      type: Array,
+      default: () => ["png", "jpg", "jpeg"],
+    },
+    // 鏄惁鏄剧ず鎻愮ず
+    isShowTip: {
+      type: Boolean,
+      default: true
+    }
+  },
+  data() {
+    return {
+      number: 0,
+      uploadList: [],
+      dialogImageUrl: "",
+      dialogVisible: false,
+      hideUpload: false,
+      baseUrl: process.env.VUE_APP_BASE_API,
+      uploadImgUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 涓婁紶鐨勫浘鐗囨湇鍔″櫒鍦板潃
+      headers: {
+        Authorization: "Bearer " + getToken(),
+      },
+      fileList: []
+    };
+  },
+  watch: {
+    value: {
+      handler(val) {
+        if (val) {
+          // 棣栧厛灏嗗�艰浆涓烘暟缁�
+          const list = Array.isArray(val) ? val : this.value.split(',');
+          // 鐒跺悗灏嗘暟缁勮浆涓哄璞℃暟缁�
+          this.fileList = list.map(item => {
+            if (typeof item === "string") {
+              if (item.indexOf(this.baseUrl) === -1) {
+                  item = { name: this.baseUrl + item, url: this.baseUrl + item };
+              } else {
+                  item = { name: item, url: item };
+              }
+            }
+            return item;
+          });
+        } else {
+          this.fileList = [];
+          return [];
+        }
+      },
+      deep: true,
+      immediate: true
+    }
+  },
+  computed: {
+    // 鏄惁鏄剧ず鎻愮ず
+    showTip() {
+      return this.isShowTip && (this.fileType || this.fileSize);
+    },
+  },
+  methods: {
+    // 涓婁紶鍓峫oading鍔犺浇
+    handleBeforeUpload(file) {
+      let isImg = false;
+      if (this.fileType.length) {
+        let fileExtension = "";
+        if (file.name.lastIndexOf(".") > -1) {
+          fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
+        }
+        isImg = this.fileType.some(type => {
+          if (file.type.indexOf(type) > -1) return true;
+          if (fileExtension && fileExtension.indexOf(type) > -1) return true;
+          return false;
+        });
+      } else {
+        isImg = file.type.indexOf("image") > -1;
+      }
+
+      if (!isImg) {
+        this.$modal.msgError(`鏂囦欢鏍煎紡涓嶆纭�, 璇蜂笂浼�${this.fileType.join("/")}鍥剧墖鏍煎紡鏂囦欢!`);
+        return false;
+      }
+      if (this.fileSize) {
+        const isLt = file.size / 1024 / 1024 < this.fileSize;
+        if (!isLt) {
+          this.$modal.msgError(`涓婁紶澶村儚鍥剧墖澶у皬涓嶈兘瓒呰繃 ${this.fileSize} MB!`);
+          return false;
+        }
+      }
+      this.$modal.loading("姝e湪涓婁紶鍥剧墖锛岃绋嶅��...");
+      this.number++;
+    },
+    // 鏂囦欢涓暟瓒呭嚭
+    handleExceed() {
+      this.$modal.msgError(`涓婁紶鏂囦欢鏁伴噺涓嶈兘瓒呰繃 ${this.limit} 涓�!`);
+    },
+    // 涓婁紶鎴愬姛鍥炶皟
+    handleUploadSuccess(res, file) {
+      if (res.code === 200) {
+        this.uploadList.push({ name: res.fileName, url: res.fileName });
+        this.uploadedSuccessfully();
+      } else {
+        this.number--;
+        this.$modal.closeLoading();
+        this.$modal.msgError(res.msg);
+        this.$refs.imageUpload.handleRemove(file);
+        this.uploadedSuccessfully();
+      }
+    },
+    // 鍒犻櫎鍥剧墖
+    handleDelete(file) {
+      const findex = this.fileList.map(f => f.name).indexOf(file.name);
+      if (findex > -1) {
+        this.fileList.splice(findex, 1);
+        this.$emit("input", this.listToString(this.fileList));
+      }
+    },
+    // 涓婁紶澶辫触
+    handleUploadError() {
+      this.$modal.msgError("涓婁紶鍥剧墖澶辫触锛岃閲嶈瘯");
+      this.$modal.closeLoading();
+    },
+    // 涓婁紶缁撴潫澶勭悊
+    uploadedSuccessfully() {
+      if (this.number > 0 && this.uploadList.length === this.number) {
+        this.fileList = this.fileList.concat(this.uploadList);
+        this.uploadList = [];
+        this.number = 0;
+        this.$emit("input", this.listToString(this.fileList));
+        this.$modal.closeLoading();
+      }
+    },
+    // 棰勮
+    handlePictureCardPreview(file) {
+      this.dialogImageUrl = file.url;
+      this.dialogVisible = true;
+    },
+    // 瀵硅薄杞垚鎸囧畾瀛楃涓插垎闅�
+    listToString(list, separator) {
+      let strs = "";
+      separator = separator || ",";
+      for (let i in list) {
+        if (list[i].url) {
+          strs += list[i].url.replace(this.baseUrl, "") + separator;
+        }
+      }
+      return strs != '' ? strs.substr(0, strs.length - 1) : '';
+    }
+  }
+};
+</script>
+<style scoped lang="scss">
+// .el-upload--picture-card 鎺у埗鍔犲彿閮ㄥ垎
+::v-deep.hide .el-upload--picture-card {
+    display: none;
+}
+// 鍘绘帀鍔ㄧ敾鏁堟灉
+::v-deep .el-list-enter-active,
+::v-deep .el-list-leave-active {
+    transition: all 0s;
+}
+
+::v-deep .el-list-enter, .el-list-leave-active {
+  opacity: 0;
+  transform: translateY(0);
+}
+</style>
+
diff --git a/jcdm-ui/src/components/Pagination/index.vue b/jcdm-ui/src/components/Pagination/index.vue
new file mode 100644
index 0000000..56f5a6b
--- /dev/null
+++ b/jcdm-ui/src/components/Pagination/index.vue
@@ -0,0 +1,114 @@
+<template>
+  <div :class="{'hidden':hidden}" class="pagination-container">
+    <el-pagination
+      :background="background"
+      :current-page.sync="currentPage"
+      :page-size.sync="pageSize"
+      :layout="layout"
+      :page-sizes="pageSizes"
+      :pager-count="pagerCount"
+      :total="total"
+      v-bind="$attrs"
+      @size-change="handleSizeChange"
+      @current-change="handleCurrentChange"
+    />
+  </div>
+</template>
+
+<script>
+import { scrollTo } from '@/utils/scroll-to'
+
+export default {
+  name: 'Pagination',
+  props: {
+    total: {
+      required: true,
+      type: Number
+    },
+    page: {
+      type: Number,
+      default: 1
+    },
+    limit: {
+      type: Number,
+      default: 20
+    },
+    pageSizes: {
+      type: Array,
+      default() {
+        return [10, 20, 30, 50]
+      }
+    },
+    // 绉诲姩绔〉鐮佹寜閽殑鏁伴噺绔粯璁ゅ��5
+    pagerCount: {
+      type: Number,
+      default: document.body.clientWidth < 992 ? 5 : 7
+    },
+    layout: {
+      type: String,
+      default: 'total, sizes, prev, pager, next, jumper'
+    },
+    background: {
+      type: Boolean,
+      default: true
+    },
+    autoScroll: {
+      type: Boolean,
+      default: true
+    },
+    hidden: {
+      type: Boolean,
+      default: false
+    }
+  },
+  data() {
+    return {
+    };
+  },
+  computed: {
+    currentPage: {
+      get() {
+        return this.page
+      },
+      set(val) {
+        this.$emit('update:page', val)
+      }
+    },
+    pageSize: {
+      get() {
+        return this.limit
+      },
+      set(val) {
+        this.$emit('update:limit', val)
+      }
+    }
+  },
+  methods: {
+    handleSizeChange(val) {
+      if (this.currentPage * val > this.total) {
+        this.currentPage = 1
+      }
+      this.$emit('pagination', { page: this.currentPage, limit: val })
+      if (this.autoScroll) {
+        scrollTo(0, 800)
+      }
+    },
+    handleCurrentChange(val) {
+      this.$emit('pagination', { page: val, limit: this.pageSize })
+      if (this.autoScroll) {
+        scrollTo(0, 800)
+      }
+    }
+  }
+}
+</script>
+
+<style scoped>
+.pagination-container {
+  background: #fff;
+  padding: 32px 16px;
+}
+.pagination-container.hidden {
+  display: none;
+}
+</style>
diff --git a/jcdm-ui/src/components/PanThumb/index.vue b/jcdm-ui/src/components/PanThumb/index.vue
new file mode 100644
index 0000000..1bcf417
--- /dev/null
+++ b/jcdm-ui/src/components/PanThumb/index.vue
@@ -0,0 +1,142 @@
+<template>
+  <div :style="{zIndex:zIndex,height:height,width:width}" class="pan-item">
+    <div class="pan-info">
+      <div class="pan-info-roles-container">
+        <slot />
+      </div>
+    </div>
+    <!-- eslint-disable-next-line -->
+    <div :style="{backgroundImage: `url(${image})`}" class="pan-thumb"></div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'PanThumb',
+  props: {
+    image: {
+      type: String,
+      required: true
+    },
+    zIndex: {
+      type: Number,
+      default: 1
+    },
+    width: {
+      type: String,
+      default: '150px'
+    },
+    height: {
+      type: String,
+      default: '150px'
+    }
+  }
+}
+</script>
+
+<style scoped>
+.pan-item {
+  width: 200px;
+  height: 200px;
+  border-radius: 50%;
+  display: inline-block;
+  position: relative;
+  cursor: default;
+  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
+}
+
+.pan-info-roles-container {
+  padding: 20px;
+  text-align: center;
+}
+
+.pan-thumb {
+  width: 100%;
+  height: 100%;
+  background-position: center center;
+  background-size: cover;
+  border-radius: 50%;
+  overflow: hidden;
+  position: absolute;
+  transform-origin: 95% 40%;
+  transition: all 0.3s ease-in-out;
+}
+
+/* .pan-thumb:after {
+  content: '';
+  width: 8px;
+  height: 8px;
+  position: absolute;
+  border-radius: 50%;
+  top: 40%;
+  left: 95%;
+  margin: -4px 0 0 -4px;
+  background: radial-gradient(ellipse at center, rgba(14, 14, 14, 1) 0%, rgba(125, 126, 125, 1) 100%);
+  box-shadow: 0 0 1px rgba(255, 255, 255, 0.9);
+} */
+
+.pan-info {
+  position: absolute;
+  width: inherit;
+  height: inherit;
+  border-radius: 50%;
+  overflow: hidden;
+  box-shadow: inset 0 0 0 5px rgba(0, 0, 0, 0.05);
+}
+
+.pan-info h3 {
+  color: #fff;
+  text-transform: uppercase;
+  position: relative;
+  letter-spacing: 2px;
+  font-size: 18px;
+  margin: 0 60px;
+  padding: 22px 0 0 0;
+  height: 85px;
+  font-family: 'Open Sans', Arial, sans-serif;
+  text-shadow: 0 0 1px #fff, 0 1px 2px rgba(0, 0, 0, 0.3);
+}
+
+.pan-info p {
+  color: #fff;
+  padding: 10px 5px;
+  font-style: italic;
+  margin: 0 30px;
+  font-size: 12px;
+  border-top: 1px solid rgba(255, 255, 255, 0.5);
+}
+
+.pan-info p a {
+  display: block;
+  color: #333;
+  width: 80px;
+  height: 80px;
+  background: rgba(255, 255, 255, 0.3);
+  border-radius: 50%;
+  color: #fff;
+  font-style: normal;
+  font-weight: 700;
+  text-transform: uppercase;
+  font-size: 9px;
+  letter-spacing: 1px;
+  padding-top: 24px;
+  margin: 7px auto 0;
+  font-family: 'Open Sans', Arial, sans-serif;
+  opacity: 0;
+  transition: transform 0.3s ease-in-out 0.2s, opacity 0.3s ease-in-out 0.2s, background 0.2s linear 0s;
+  transform: translateX(60px) rotate(90deg);
+}
+
+.pan-info p a:hover {
+  background: rgba(255, 255, 255, 0.5);
+}
+
+.pan-item:hover .pan-thumb {
+  transform: rotate(-110deg);
+}
+
+.pan-item:hover .pan-info p a {
+  opacity: 1;
+  transform: translateX(0px) rotate(0deg);
+}
+</style>
diff --git a/jcdm-ui/src/components/ParentView/index.vue b/jcdm-ui/src/components/ParentView/index.vue
new file mode 100644
index 0000000..7bf6148
--- /dev/null
+++ b/jcdm-ui/src/components/ParentView/index.vue
@@ -0,0 +1,3 @@
+<template >
+  <router-view />
+</template>
diff --git a/jcdm-ui/src/components/RightPanel/index.vue b/jcdm-ui/src/components/RightPanel/index.vue
new file mode 100644
index 0000000..5abeecb
--- /dev/null
+++ b/jcdm-ui/src/components/RightPanel/index.vue
@@ -0,0 +1,106 @@
+<template>
+  <div ref="rightPanel" class="rightPanel-container">
+    <div class="rightPanel-background" />
+    <div class="rightPanel">
+      <div class="rightPanel-items">
+        <slot />
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'RightPanel',
+  props: {
+    clickNotClose: {
+      default: false,
+      type: Boolean
+    }
+  },
+  computed: {
+    show: {
+      get() {
+        return this.$store.state.settings.showSettings
+      },
+      set(val) {
+        this.$store.dispatch('settings/changeSetting', {
+          key: 'showSettings',
+          value: val
+        })
+      }
+    }
+  },
+  watch: {
+    show(value) {
+      if (value && !this.clickNotClose) {
+        this.addEventClick()
+      }
+    }
+  },
+  mounted() {
+    this.addEventClick()
+  },
+  beforeDestroy() {
+    const elx = this.$refs.rightPanel
+    elx.remove()
+  },
+  methods: {
+    addEventClick() {
+      window.addEventListener('click', this.closeSidebar)
+    },
+    closeSidebar(evt) {
+      const parent = evt.target.closest('.el-drawer__body')
+      if (!parent) {
+        this.show = false
+        window.removeEventListener('click', this.closeSidebar)
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.rightPanel-background {
+  position: fixed;
+  top: 0;
+  left: 0;
+  opacity: 0;
+  transition: opacity .3s cubic-bezier(.7, .3, .1, 1);
+  background: rgba(0, 0, 0, .2);
+  z-index: -1;
+}
+
+.rightPanel {
+  width: 100%;
+  max-width: 260px;
+  height: 100vh;
+  position: fixed;
+  top: 0;
+  right: 0;
+  box-shadow: 0px 0px 15px 0px rgba(0, 0, 0, .05);
+  transition: all .25s cubic-bezier(.7, .3, .1, 1);
+  transform: translate(100%);
+  background: #fff;
+  z-index: 40000;
+}
+
+.handle-button {
+  width: 48px;
+  height: 48px;
+  position: absolute;
+  left: -48px;
+  text-align: center;
+  font-size: 24px;
+  border-radius: 6px 0 0 6px !important;
+  z-index: 0;
+  pointer-events: auto;
+  cursor: pointer;
+  color: #fff;
+  line-height: 48px;
+  i {
+    font-size: 24px;
+    line-height: 48px;
+  }
+}
+</style>
diff --git a/jcdm-ui/src/components/RightToolbar/index.vue b/jcdm-ui/src/components/RightToolbar/index.vue
new file mode 100644
index 0000000..67da293
--- /dev/null
+++ b/jcdm-ui/src/components/RightToolbar/index.vue
@@ -0,0 +1,129 @@
+<template>
+  <div class="top-right-btn" :style="style">
+    <el-row>
+      <el-tooltip class="item" effect="dark" :content="showSearch ? '闅愯棌鎼滅储' : '鏄剧ず鎼滅储'" placement="top" v-if="search">
+        <el-button size="mini" circle icon="el-icon-search" @click="toggleSearch()" />
+      </el-tooltip>
+      <el-tooltip class="item" effect="dark" content="鍒锋柊" placement="top">
+        <el-button size="mini" circle icon="el-icon-refresh" @click="refresh()" />
+      </el-tooltip>
+      <el-tooltip class="item" effect="dark" content="鏄鹃殣鍒�" placement="top" v-if="columns">
+        <el-button size="mini" circle icon="el-icon-menu" @click="showColumn()" v-if="showColumnsType == 'transfer'"/>
+        <el-dropdown trigger="click" :hide-on-click="false" style="padding-left: 12px" v-if="showColumnsType == 'checkbox'">
+          <el-button size="mini" circle icon="el-icon-menu" />
+          <el-dropdown-menu slot="dropdown">
+            <template v-for="item in columns">
+              <el-dropdown-item :key="item.key">
+                <el-checkbox :checked="item.visible" @change="checkboxChange($event, item.label)" :label="item.label" />
+              </el-dropdown-item>
+            </template>
+          </el-dropdown-menu>
+        </el-dropdown>
+      </el-tooltip>
+    </el-row>
+    <el-dialog :title="title" :visible.sync="open" append-to-body>
+      <el-transfer
+        :titles="['鏄剧ず', '闅愯棌']"
+        v-model="value"
+        :data="columns"
+        @change="dataChange"
+      ></el-transfer>
+    </el-dialog>
+  </div>
+</template>
+<script>
+export default {
+  name: "RightToolbar",
+  data() {
+    return {
+      // 鏄鹃殣鏁版嵁
+      value: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "鏄剧ず/闅愯棌",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+    };
+  },
+  props: {
+    /* 鏄惁鏄剧ず妫�绱㈡潯浠� */
+    showSearch: {
+      type: Boolean,
+      default: true,
+    },
+    /* 鏄鹃殣鍒椾俊鎭� */
+    columns: {
+      type: Array,
+    },
+    /* 鏄惁鏄剧ず妫�绱㈠浘鏍� */
+    search: {
+      type: Boolean,
+      default: true,
+    },
+    /* 鏄鹃殣鍒楃被鍨嬶紙transfer绌挎妗嗐�乧heckbox澶嶉�夋锛� */
+    showColumnsType: {
+      type: String,
+      default: "checkbox",
+    },
+    /* 鍙冲杈硅窛 */
+    gutter: {
+      type: Number,
+      default: 10,
+    },
+  },
+  computed: {
+    style() {
+      const ret = {};
+      if (this.gutter) {
+        ret.marginRight = `${this.gutter / 2}px`;
+      }
+      return ret;
+    }
+  },
+  created() {
+    if (this.showColumnsType == 'transfer') {
+      // 鏄鹃殣鍒楀垵濮嬮粯璁ら殣钘忓垪
+      for (let item in this.columns) {
+        if (this.columns[item].visible === false) {
+          this.value.push(parseInt(item));
+        }
+      }
+    }
+  },
+  methods: {
+    // 鎼滅储
+    toggleSearch() {
+      this.$emit("update:showSearch", !this.showSearch);
+    },
+    // 鍒锋柊
+    refresh() {
+      this.$emit("queryTable");
+    },
+    // 鍙充晶鍒楄〃鍏冪礌鍙樺寲
+    dataChange(data) {
+      for (let item in this.columns) {
+        const key = this.columns[item].key;
+        this.columns[item].visible = !data.includes(key);
+      }
+    },
+    // 鎵撳紑鏄鹃殣鍒梔ialog
+    showColumn() {
+      this.open = true;
+    },
+    // 鍕鹃��
+    checkboxChange(event, label) {
+      this.columns.filter(item => item.label == label)[0].visible = event;
+    }
+  },
+};
+</script>
+<style lang="scss" scoped>
+::v-deep .el-transfer__button {
+  border-radius: 50%;
+  padding: 12px;
+  display: block;
+  margin-left: 0px;
+}
+::v-deep .el-transfer__button:first-child {
+  margin-bottom: 10px;
+}
+</style>
diff --git a/jcdm-ui/src/components/RuoYi/Doc/index.vue b/jcdm-ui/src/components/RuoYi/Doc/index.vue
new file mode 100644
index 0000000..75fa864
--- /dev/null
+++ b/jcdm-ui/src/components/RuoYi/Doc/index.vue
@@ -0,0 +1,21 @@
+<template>
+  <div>
+    <svg-icon icon-class="question" @click="goto" />
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'RuoYiDoc',
+  data() {
+    return {
+      url: 'http://doc.ruoyi.vip/ruoyi-vue'
+    }
+  },
+  methods: {
+    goto() {
+      window.open(this.url)
+    }
+  }
+}
+</script>
\ No newline at end of file
diff --git a/jcdm-ui/src/components/RuoYi/Git/index.vue b/jcdm-ui/src/components/RuoYi/Git/index.vue
new file mode 100644
index 0000000..f0967bf
--- /dev/null
+++ b/jcdm-ui/src/components/RuoYi/Git/index.vue
@@ -0,0 +1,21 @@
+<template>
+  <div>
+    <svg-icon icon-class="github" @click="goto" />
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'JCGit',
+  data() {
+    return {
+      url: 'http://192.168.0.189:8442/r/Jcdm-Mes.git'
+    }
+  },
+  methods: {
+    goto() {
+      window.open(this.url)
+    }
+  }
+}
+</script>
diff --git a/jcdm-ui/src/components/Screenfull/index.vue b/jcdm-ui/src/components/Screenfull/index.vue
new file mode 100644
index 0000000..d4e539c
--- /dev/null
+++ b/jcdm-ui/src/components/Screenfull/index.vue
@@ -0,0 +1,57 @@
+<template>
+  <div>
+    <svg-icon :icon-class="isFullscreen?'exit-fullscreen':'fullscreen'" @click="click" />
+  </div>
+</template>
+
+<script>
+import screenfull from 'screenfull'
+
+export default {
+  name: 'Screenfull',
+  data() {
+    return {
+      isFullscreen: false
+    }
+  },
+  mounted() {
+    this.init()
+  },
+  beforeDestroy() {
+    this.destroy()
+  },
+  methods: {
+    click() {
+      if (!screenfull.isEnabled) {
+        this.$message({ message: '浣犵殑娴忚鍣ㄤ笉鏀寔鍏ㄥ睆', type: 'warning' })
+        return false
+      }
+      screenfull.toggle()
+    },
+    change() {
+      this.isFullscreen = screenfull.isFullscreen
+    },
+    init() {
+      if (screenfull.isEnabled) {
+        screenfull.on('change', this.change)
+      }
+    },
+    destroy() {
+      if (screenfull.isEnabled) {
+        screenfull.off('change', this.change)
+      }
+    }
+  }
+}
+</script>
+
+<style scoped>
+.screenfull-svg {
+  display: inline-block;
+  cursor: pointer;
+  fill: #5a5e66;;
+  width: 20px;
+  height: 20px;
+  vertical-align: 10px;
+}
+</style>
diff --git a/jcdm-ui/src/components/SizeSelect/index.vue b/jcdm-ui/src/components/SizeSelect/index.vue
new file mode 100644
index 0000000..069b5de
--- /dev/null
+++ b/jcdm-ui/src/components/SizeSelect/index.vue
@@ -0,0 +1,56 @@
+<template>
+  <el-dropdown trigger="click" @command="handleSetSize">
+    <div>
+      <svg-icon class-name="size-icon" icon-class="size" />
+    </div>
+    <el-dropdown-menu slot="dropdown">
+      <el-dropdown-item v-for="item of sizeOptions" :key="item.value" :disabled="size===item.value" :command="item.value">
+        {{ item.label }}
+      </el-dropdown-item>
+    </el-dropdown-menu>
+  </el-dropdown>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      sizeOptions: [
+        { label: 'Default', value: 'default' },
+        { label: 'Medium', value: 'medium' },
+        { label: 'Small', value: 'small' },
+        { label: 'Mini', value: 'mini' }
+      ]
+    }
+  },
+  computed: {
+    size() {
+      return this.$store.getters.size
+    }
+  },
+  methods: {
+    handleSetSize(size) {
+      this.$ELEMENT.size = size
+      this.$store.dispatch('app/setSize', size)
+      this.refreshView()
+      this.$message({
+        message: 'Switch Size Success',
+        type: 'success'
+      })
+    },
+    refreshView() {
+      // In order to make the cached page re-rendered
+      this.$store.dispatch('tagsView/delAllCachedViews', this.$route)
+
+      const { fullPath } = this.$route
+
+      this.$nextTick(() => {
+        this.$router.replace({
+          path: '/redirect' + fullPath
+        })
+      })
+    }
+  }
+
+}
+</script>
diff --git a/jcdm-ui/src/components/SvgIcon/index.vue b/jcdm-ui/src/components/SvgIcon/index.vue
new file mode 100644
index 0000000..e4bf5ad
--- /dev/null
+++ b/jcdm-ui/src/components/SvgIcon/index.vue
@@ -0,0 +1,61 @@
+<template>
+  <div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" />
+  <svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
+    <use :xlink:href="iconName" />
+  </svg>
+</template>
+
+<script>
+import { isExternal } from '@/utils/validate'
+
+export default {
+  name: 'SvgIcon',
+  props: {
+    iconClass: {
+      type: String,
+      required: true
+    },
+    className: {
+      type: String,
+      default: ''
+    }
+  },
+  computed: {
+    isExternal() {
+      return isExternal(this.iconClass)
+    },
+    iconName() {
+      return `#icon-${this.iconClass}`
+    },
+    svgClass() {
+      if (this.className) {
+        return 'svg-icon ' + this.className
+      } else {
+        return 'svg-icon'
+      }
+    },
+    styleExternalIcon() {
+      return {
+        mask: `url(${this.iconClass}) no-repeat 50% 50%`,
+        '-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`
+      }
+    }
+  }
+}
+</script>
+
+<style scoped>
+.svg-icon {
+  width: 1em;
+  height: 1em;
+  vertical-align: -0.15em;
+  fill: currentColor;
+  overflow: hidden;
+}
+
+.svg-external-icon {
+  background-color: currentColor;
+  mask-size: cover!important;
+  display: inline-block;
+}
+</style>
diff --git a/jcdm-ui/src/components/ThemePicker/index.vue b/jcdm-ui/src/components/ThemePicker/index.vue
new file mode 100644
index 0000000..1714e1f
--- /dev/null
+++ b/jcdm-ui/src/components/ThemePicker/index.vue
@@ -0,0 +1,173 @@
+<template>
+  <el-color-picker
+    v-model="theme"
+    :predefine="['#409EFF', '#1890ff', '#304156','#212121','#11a983', '#13c2c2', '#6959CD', '#f5222d', ]"
+    class="theme-picker"
+    popper-class="theme-picker-dropdown"
+  />
+</template>
+
+<script>
+const version = require('element-ui/package.json').version // element-ui version from node_modules
+const ORIGINAL_THEME = '#409EFF' // default color
+
+export default {
+  data() {
+    return {
+      chalk: '', // content of theme-chalk css
+      theme: ''
+    }
+  },
+  computed: {
+    defaultTheme() {
+      return this.$store.state.settings.theme
+    }
+  },
+  watch: {
+    defaultTheme: {
+      handler: function(val, oldVal) {
+        this.theme = val
+      },
+      immediate: true
+    },
+    async theme(val) {
+      await this.setTheme(val)
+    }
+  },
+  created() {
+    if(this.defaultTheme !== ORIGINAL_THEME) {
+      this.setTheme(this.defaultTheme)
+    }
+  },
+
+  methods: {
+    async setTheme(val) {
+      const oldVal = this.chalk ? this.theme : ORIGINAL_THEME
+      if (typeof val !== 'string') return
+      const themeCluster = this.getThemeCluster(val.replace('#', ''))
+      const originalCluster = this.getThemeCluster(oldVal.replace('#', ''))
+
+      const getHandler = (variable, id) => {
+        return () => {
+          const originalCluster = this.getThemeCluster(ORIGINAL_THEME.replace('#', ''))
+          const newStyle = this.updateStyle(this[variable], originalCluster, themeCluster)
+
+          let styleTag = document.getElementById(id)
+          if (!styleTag) {
+            styleTag = document.createElement('style')
+            styleTag.setAttribute('id', id)
+            document.head.appendChild(styleTag)
+          }
+          styleTag.innerText = newStyle
+        }
+      }
+
+      if (!this.chalk) {
+        const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css`
+        await this.getCSSString(url, 'chalk')
+      }
+
+      const chalkHandler = getHandler('chalk', 'chalk-style')
+
+      chalkHandler()
+
+      const styles = [].slice.call(document.querySelectorAll('style'))
+        .filter(style => {
+          const text = style.innerText
+          return new RegExp(oldVal, 'i').test(text) && !/Chalk Variables/.test(text)
+        })
+      styles.forEach(style => {
+        const { innerText } = style
+        if (typeof innerText !== 'string') return
+        style.innerText = this.updateStyle(innerText, originalCluster, themeCluster)
+      })
+
+      this.$emit('change', val)
+    },
+
+    updateStyle(style, oldCluster, newCluster) {
+      let newStyle = style
+      oldCluster.forEach((color, index) => {
+        newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index])
+      })
+      return newStyle
+    },
+
+    getCSSString(url, variable) {
+      return new Promise(resolve => {
+        const xhr = new XMLHttpRequest()
+        xhr.onreadystatechange = () => {
+          if (xhr.readyState === 4 && xhr.status === 200) {
+            this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, '')
+            resolve()
+          }
+        }
+        xhr.open('GET', url)
+        xhr.send()
+      })
+    },
+
+    getThemeCluster(theme) {
+      const tintColor = (color, tint) => {
+        let red = parseInt(color.slice(0, 2), 16)
+        let green = parseInt(color.slice(2, 4), 16)
+        let blue = parseInt(color.slice(4, 6), 16)
+
+        if (tint === 0) { // when primary color is in its rgb space
+          return [red, green, blue].join(',')
+        } else {
+          red += Math.round(tint * (255 - red))
+          green += Math.round(tint * (255 - green))
+          blue += Math.round(tint * (255 - blue))
+
+          red = red.toString(16)
+          green = green.toString(16)
+          blue = blue.toString(16)
+
+          return `#${red}${green}${blue}`
+        }
+      }
+
+      const shadeColor = (color, shade) => {
+        let red = parseInt(color.slice(0, 2), 16)
+        let green = parseInt(color.slice(2, 4), 16)
+        let blue = parseInt(color.slice(4, 6), 16)
+
+        red = Math.round((1 - shade) * red)
+        green = Math.round((1 - shade) * green)
+        blue = Math.round((1 - shade) * blue)
+
+        red = red.toString(16)
+        green = green.toString(16)
+        blue = blue.toString(16)
+
+        return `#${red}${green}${blue}`
+      }
+
+      const clusters = [theme]
+      for (let i = 0; i <= 9; i++) {
+        clusters.push(tintColor(theme, Number((i / 10).toFixed(2))))
+      }
+      clusters.push(shadeColor(theme, 0.1))
+      return clusters
+    }
+  }
+}
+</script>
+
+<style>
+.theme-message,
+.theme-picker-dropdown {
+  z-index: 99999 !important;
+}
+
+.theme-picker .el-color-picker__trigger {
+  height: 26px !important;
+  width: 26px !important;
+  padding: 2px;
+}
+
+.theme-picker-dropdown .el-color-dropdown__link-btn {
+  display: none;
+}
+</style>
diff --git a/jcdm-ui/src/components/TopNav/index.vue b/jcdm-ui/src/components/TopNav/index.vue
new file mode 100644
index 0000000..86a91c4
--- /dev/null
+++ b/jcdm-ui/src/components/TopNav/index.vue
@@ -0,0 +1,195 @@
+<template>
+  <el-menu
+    :default-active="activeMenu"
+    mode="horizontal"
+    @select="handleSelect"
+  >
+    <template v-for="(item, index) in topMenus">
+      <el-menu-item :style="{'--theme': theme}" :index="item.path" :key="index" v-if="index < visibleNumber">
+        <svg-icon
+        v-if="item.meta && item.meta.icon && item.meta.icon !== '#'"
+        :icon-class="item.meta.icon"/>
+        {{ item.meta.title }}
+      </el-menu-item>
+    </template>
+
+    <!-- 椤堕儴鑿滃崟瓒呭嚭鏁伴噺鎶樺彔 -->
+    <el-submenu :style="{'--theme': theme}" index="more" v-if="topMenus.length > visibleNumber">
+      <template slot="title">鏇村鑿滃崟</template>
+      <template v-for="(item, index) in topMenus">
+        <el-menu-item
+          :index="item.path"
+          :key="index"
+          v-if="index >= visibleNumber">
+          <svg-icon
+            v-if="item.meta && item.meta.icon && item.meta.icon !== '#'"
+            :icon-class="item.meta.icon"/>
+          {{ item.meta.title }}
+        </el-menu-item>
+      </template>
+    </el-submenu>
+  </el-menu>
+</template>
+
+<script>
+import { constantRoutes } from "@/router";
+
+// 闅愯棌渚ц竟鏍忚矾鐢�
+const hideList = ['/index', '/user/profile'];
+
+export default {
+  data() {
+    return {
+      // 椤堕儴鏍忓垵濮嬫暟
+      visibleNumber: 5,
+      // 褰撳墠婵�娲昏彍鍗曠殑 index
+      currentIndex: undefined
+    };
+  },
+  computed: {
+    theme() {
+      return this.$store.state.settings.theme;
+    },
+    // 椤堕儴鏄剧ず鑿滃崟
+    topMenus() {
+      let topMenus = [];
+      this.routers.map((menu) => {
+        if (menu.hidden !== true) {
+          // 鍏煎椤堕儴鏍忎竴绾ц彍鍗曞唴閮ㄨ烦杞�
+          if (menu.path === "/") {
+            topMenus.push(menu.children[0]);
+          } else {
+            topMenus.push(menu);
+          }
+        }
+      });
+      return topMenus;
+    },
+    // 鎵�鏈夌殑璺敱淇℃伅
+    routers() {
+      return this.$store.state.permission.topbarRouters;
+    },
+    // 璁剧疆瀛愯矾鐢�
+    childrenMenus() {
+      var childrenMenus = [];
+      this.routers.map((router) => {
+        for (var item in router.children) {
+          if (router.children[item].parentPath === undefined) {
+            if(router.path === "/") {
+              router.children[item].path = "/" + router.children[item].path;
+            } else {
+              if(!this.ishttp(router.children[item].path)) {
+                router.children[item].path = router.path + "/" + router.children[item].path;
+              }
+            }
+            router.children[item].parentPath = router.path;
+          }
+          childrenMenus.push(router.children[item]);
+        }
+      });
+      return constantRoutes.concat(childrenMenus);
+    },
+    // 榛樿婵�娲荤殑鑿滃崟
+    activeMenu() {
+      const path = this.$route.path;
+      let activePath = path;
+      if (path !== undefined && path.lastIndexOf("/") > 0 && hideList.indexOf(path) === -1) {
+        const tmpPath = path.substring(1, path.length);
+        activePath = "/" + tmpPath.substring(0, tmpPath.indexOf("/"));
+        if (!this.$route.meta.link) {
+          this.$store.dispatch('app/toggleSideBarHide', false);
+        }
+      } else if(!this.$route.children) {
+        activePath = path;
+        this.$store.dispatch('app/toggleSideBarHide', true);
+      }
+      this.activeRoutes(activePath);
+      return activePath;
+    },
+  },
+  beforeMount() {
+    window.addEventListener('resize', this.setVisibleNumber)
+  },
+  beforeDestroy() {
+    window.removeEventListener('resize', this.setVisibleNumber)
+  },
+  mounted() {
+    this.setVisibleNumber();
+  },
+  methods: {
+    // 鏍规嵁瀹藉害璁$畻璁剧疆鏄剧ず鏍忔暟
+    setVisibleNumber() {
+      const width = document.body.getBoundingClientRect().width / 3;
+      this.visibleNumber = parseInt(width / 85);
+    },
+    // 鑿滃崟閫夋嫨浜嬩欢
+    handleSelect(key, keyPath) {
+      this.currentIndex = key;
+      const route = this.routers.find(item => item.path === key);
+      if (this.ishttp(key)) {
+        // http(s):// 璺緞鏂扮獥鍙f墦寮�
+        window.open(key, "_blank");
+      } else if (!route || !route.children) {
+        // 娌℃湁瀛愯矾鐢辫矾寰勫唴閮ㄦ墦寮�
+        const routeMenu = this.childrenMenus.find(item => item.path === key);
+        if (routeMenu && routeMenu.query) {
+          let query = JSON.parse(routeMenu.query);
+          this.$router.push({ path: key, query: query });
+        } else {
+          this.$router.push({ path: key });
+        }
+        this.$store.dispatch('app/toggleSideBarHide', true);
+      } else {
+        // 鏄剧ず宸︿晶鑱斿姩鑿滃崟
+        this.activeRoutes(key);
+        this.$store.dispatch('app/toggleSideBarHide', false);
+      }
+    },
+    // 褰撳墠婵�娲荤殑璺敱
+    activeRoutes(key) {
+      var routes = [];
+      if (this.childrenMenus && this.childrenMenus.length > 0) {
+        this.childrenMenus.map((item) => {
+          if (key == item.parentPath || (key == "index" && "" == item.path)) {
+            routes.push(item);
+          }
+        });
+      }
+      if(routes.length > 0) {
+        this.$store.commit("SET_SIDEBAR_ROUTERS", routes);
+      } else {
+        this.$store.dispatch('app/toggleSideBarHide', true);
+      }
+    },
+    ishttp(url) {
+      return url.indexOf('http://') !== -1 || url.indexOf('https://') !== -1
+    }
+  },
+};
+</script>
+
+<style lang="scss">
+.topmenu-container.el-menu--horizontal > .el-menu-item {
+  float: left;
+  height: 50px !important;
+  line-height: 50px !important;
+  color: #999093 !important;
+  padding: 0 5px !important;
+  margin: 0 10px !important;
+}
+
+.topmenu-container.el-menu--horizontal > .el-menu-item.is-active, .el-menu--horizontal > .el-submenu.is-active .el-submenu__title {
+  border-bottom: 2px solid #{'var(--theme)'} !important;
+  color: #303133;
+}
+
+/* submenu item */
+.topmenu-container.el-menu--horizontal > .el-submenu .el-submenu__title {
+  float: left;
+  height: 50px !important;
+  line-height: 50px !important;
+  color: #999093 !important;
+  padding: 0 5px !important;
+  margin: 0 10px !important;
+}
+</style>
diff --git a/jcdm-ui/src/components/iFrame/index.vue b/jcdm-ui/src/components/iFrame/index.vue
new file mode 100644
index 0000000..426857f
--- /dev/null
+++ b/jcdm-ui/src/components/iFrame/index.vue
@@ -0,0 +1,36 @@
+<template>
+  <div v-loading="loading" :style="'height:' + height">
+    <iframe
+      :src="src"
+      frameborder="no"
+      style="width: 100%; height: 100%"
+      scrolling="auto"
+    />
+  </div>
+</template>
+<script>
+export default {
+  props: {
+    src: {
+      type: String,
+      required: true
+    },
+  },
+  data() {
+    return {
+      height: document.documentElement.clientHeight - 94.5 + "px;",
+      loading: true,
+      url: this.src
+    };
+  },
+  mounted: function () {
+    setTimeout(() => {
+      this.loading = false;
+    }, 300);
+    const that = this;
+    window.onresize = function temp() {
+      that.height = document.documentElement.clientHeight - 94.5 + "px;";
+    };
+  }
+};
+</script>
diff --git a/jcdm-ui/src/components/itemSelect/index.vue b/jcdm-ui/src/components/itemSelect/index.vue
new file mode 100644
index 0000000..282ae3f
--- /dev/null
+++ b/jcdm-ui/src/components/itemSelect/index.vue
@@ -0,0 +1,223 @@
+<template>
+  <el-dialog title="鐗╂枡浜у搧閫夋嫨"
+    v-if="showFlag"
+    :visible.sync="showFlag"
+    :modal= false
+    width="80%"
+    center
+  >
+    <el-row :gutter="20">
+      <!--鍒嗙被鏁版嵁-->
+      <el-col :span="4" :xs="24">
+        <div class="head-container">
+          <el-input
+            v-model="itemTypeName"
+            placeholder="璇疯緭鍏ュ垎绫诲悕绉�"
+            clearable
+            size="small"
+            prefix-icon="el-icon-search"
+            style="margin-bottom: 20px"
+          />
+        </div>
+        <div class="head-container">
+          <el-tree
+            :data="itemTypeOptions"
+            :props="defaultProps"
+            :expand-on-click-node="false"
+            :filter-node-method="filterNode"
+            ref="tree"
+            default-expand-all
+            @node-click="handleNodeClick"
+          />
+        </div>
+      </el-col>
+      <!--鐗╂枡鏁版嵁-->
+      <el-col :span="20" :xs="24">
+        <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+          <el-form-item label="鐗╂枡缂栫爜" prop="itemCode">
+            <el-input
+              v-model="queryParams.itemCode"
+              placeholder="璇疯緭鍏ョ墿鏂欑紪鐮�"
+              clearable
+              style="width: 240px"
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item label="鐗╂枡鍚嶇О" prop="itemName">
+            <el-input
+              v-model="queryParams.itemName"
+              placeholder="璇疯緭鍏ョ墿鏂欏悕绉�"
+              clearable
+              style="width: 240px"
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+            <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+          </el-form-item>
+        </el-form>
+        <el-table v-loading="loading" :data="itemList" @selection-change="handleSelectionChange">
+          <el-table-column type="selection" width="50" align="center" />
+          <el-table-column label="鐗╂枡缂栫爜" width = "120" align="center" key="itemCode" prop="itemCode" v-if="columns[0].visible" >
+          </el-table-column>
+          <el-table-column label="鐗╂枡鍚嶇О" min-width="120" align="left" key="itemName" prop="itemName" v-if="columns[1].visible" :show-overflow-tooltip="true" />
+          <el-table-column label="瑙勬牸鍨嬪彿" align="left" key="specification" prop="specification" v-if="columns[2].visible" :show-overflow-tooltip="true" />
+          <el-table-column label="鍗曚綅" align="center" key="unitOfMeasure" prop="unitOfMeasure" v-if="columns[3].visible" :show-overflow-tooltip="true" />
+          <el-table-column label="鐗╂枡/浜у搧" align="center" key="itemOrProduct" prop="itemOrProduct" v-if="columns[4].visible" :show-overflow-tooltip="true" >
+            <template slot-scope="scope">
+              <dict-tag :options="dict.type.mes_item_product" :value="scope.row.itemOrProduct"/>
+            </template>
+          </el-table-column>
+          <el-table-column label="鎵�灞炲垎绫�" align="center" key="itemTypeName" prop="itemTypeName" v-if="columns[5].visible" width="120" />
+          <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" v-if="columns[6].visible" width="160">
+            <template slot-scope="scope">
+              <span>{{ parseTime(scope.row.createTime) }}</span>
+            </template>
+          </el-table-column>
+        </el-table>
+
+        <pagination
+          v-show="total>0"
+          :total="total"
+          :page.sync="queryParams.pageNum"
+          :limit.sync="queryParams.pageSize"
+          @pagination="getList"
+        />
+      </el-col>
+    </el-row>
+    <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="confirmSelect">纭� 瀹�</el-button>
+        <el-button @click="showFlag=false">鍙� 娑�</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { listMdItem, getMdItem, delMdItem, addMdItem, updateMdItem} from "@/api/mes/md/mdItem";
+import { listAllUnitmeasure} from "@/api/mes/md/unitmeasure";
+import {genCode} from "@/api/system/autocode/rule"
+import { getToken } from "@/utils/auth";
+import { treeselect } from "@/api/mes/md/itemtype";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+
+export default {
+  name: "MdItemSelect",
+  dicts: ['sys_yes_no','mes_item_product'],
+  components: { Treeselect },
+  data() {
+    return {
+      showFlag:false,
+
+      // 閫変腑鏁扮粍
+      ids: [],
+      selectedRows: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 鐗╂枡浜у搧琛ㄦ牸鏁版嵁
+      itemList: null,
+      // 閮ㄩ棬鏍戦�夐」
+      itemTypeOptions: undefined,
+      // 閮ㄩ棬鍚嶇О
+      itemTypeName: undefined,
+      defaultProps: {
+        children: "children",
+        label: "label"
+      },
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        itemCode: undefined,
+        itemName: undefined,
+        itemTypeId: 0
+      },
+      // 鍒椾俊鎭�
+      columns: [
+        { key: 0, label: `鐗╂枡/浜у搧缂栫爜`, visible: true },
+        { key: 1, label: `鐗╂枡/浜у搧鍚嶇О`, visible: true },
+        { key: 2, label: `瑙勬牸鍨嬪彿`, visible: true },
+        { key: 3, label: `鍗曚綅`, visible: true },
+        { key: 4, label: `鐗╂枡/浜у搧`, visible: true },
+        { key: 5, label: `鐗╂枡鍒嗙被`, visible: true },
+        { key: 6, label: `鍒涘缓鏃堕棿`, visible: true }
+      ]
+    };
+  },
+  watch: {
+    // 鏍规嵁鍚嶇О绛涢�夊垎绫绘爲
+    itemTypeName(val) {
+      this.$refs.tree.filter(val);
+    }
+  },
+  created() {
+    this.getList();
+    this.getTreeselect();
+  },
+  methods: {
+    /** 鏌ヨ鐗╂枡缂栫爜鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listMdItem(this.queryParams).then(response => {
+          this.itemList = response.rows;
+          this.total = response.total;
+          this.loading = false;
+        }
+      );
+    },
+    /** 鏌ヨ鍒嗙被涓嬫媺鏍戠粨鏋� */
+    getTreeselect() {
+      treeselect().then(response => {
+        this.itemTypeOptions = response.data;
+      });
+    },
+    // 绛涢�夎妭鐐�
+    filterNode(value, data) {
+      if (!value) return true;
+      return data.label.indexOf(value) !== -1;
+    },
+    // 鑺傜偣鍗曞嚮浜嬩欢
+    handleNodeClick(data) {
+      this.queryParams.itemTypeId = data.id;
+      this.handleQuery();
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.itemId);
+      this.single = selection.length != 1;
+      this.multiple = !selection.length;
+      this.selectedRows = selection;
+    },
+    //纭畾閫変腑
+    confirmSelect(){
+        if(this.ids ==[] || this.ids.length==0){
+            this.$notify({
+                title:'鎻愮ず',
+                type:'warning',
+                message: '璇疯嚦灏戦�夋嫨涓�鏉℃暟鎹�!'
+            });
+            return;
+        }
+        this.$emit('onSelected',this.selectedRows);
+        this.showFlag = false;
+    }
+  }
+};
+</script>
\ No newline at end of file
diff --git a/jcdm-ui/src/components/itemSelect/single.vue b/jcdm-ui/src/components/itemSelect/single.vue
new file mode 100644
index 0000000..4d271fd
--- /dev/null
+++ b/jcdm-ui/src/components/itemSelect/single.vue
@@ -0,0 +1,210 @@
+<template>
+  <el-dialog title="鐗╂枡浜у搧閫夋嫨"
+             v-if="showFlag"
+             :visible.sync="showFlag"
+             :modal= false
+             width="80%"
+             center
+  >
+    <el-row :gutter="20">
+      <!--鐗╂枡鏁版嵁-->
+      <el-col :span="24" :xs="24">
+        <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+          <el-form-item label="鐗╂枡缂栫爜" prop="itemCode">
+            <el-input
+              v-model="queryParams.itemCode"
+              placeholder="璇疯緭鍏ョ墿鏂欑紪鐮�"
+              clearable
+              style="width: 240px"
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item label="鐗╂枡鍚嶇О" prop="itemName">
+            <el-input
+              v-model="queryParams.itemName"
+              placeholder="璇疯緭鍏ョ墿鏂欏悕绉�"
+              clearable
+              style="width: 240px"
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item style="float: right">
+            <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+            <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+          </el-form-item>
+        </el-form>
+        <el-table border v-loading="loading" :data="itemList" @current-change="handleCurrent" @row-dblclick="handleRowDbClick">
+          <el-table-column width="50" align="center" >
+            <template v-slot="scope">
+              <el-radio v-model="selectedItemId" :label="scope.row.id" @change="handleRowChange(scope.row)">{{""}}</el-radio>
+            </template>
+          </el-table-column>
+          <el-table-column label="鐗╂枡缂栧彿" align="center" prop="materialCode">
+          </el-table-column>
+          <el-table-column label="鐗╂枡鍚嶇О" align="center" prop="materialName">
+          </el-table-column>
+          <el-table-column label="绫诲瀷" align="center" prop="typeL">
+            <template slot-scope="scope">
+              <dict-tag :options="dict.type.material_type" :value="scope.row.typeL"/>
+            </template>
+          </el-table-column>
+          <el-table-column label="鍗曚綅" align="center" prop="unit">
+            <template slot-scope="scope">
+              <dict-tag :options="dict.type.unit" :value="scope.row.unit"/>
+            </template>
+          </el-table-column>
+          <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime">
+          </el-table-column>
+          <el-table-column label="鐘舵��" align="center" prop="status">
+            <template slot-scope="scope">
+              <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
+            </template>
+          </el-table-column>
+          <el-table-column label="鍘傚晢" align="center" prop="supplier">
+          </el-table-column>
+        </el-table>
+
+        <pagination
+          v-show="total>0"
+          :total="total"
+          :page.sync="queryParams.pageNum"
+          :limit.sync="queryParams.pageSize"
+          @pagination="getList"
+        />
+      </el-col>
+    </el-row>
+    <div slot="footer" class="dialog-footer">
+      <el-button type="primary" @click="confirmSelect">纭� 瀹�</el-button>
+      <el-button @click="showFlag=false">鍙� 娑�</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { listMaterial} from "@/api/main/bs/material/material";
+
+export default {
+  name: "MdItemSingle",
+  dicts: ['sys_yes_no','mes_item_product','material_type','unit','sys_normal_disable'],
+  data() {
+    return {
+      showFlag:false,
+      // 閫変腑鏁扮粍
+      selectedItemId: undefined,
+      selectedRows: undefined,
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 鐗╂枡浜у搧琛ㄦ牸鏁版嵁
+      itemList: null,
+      // 閮ㄩ棬鏍戦�夐」
+      itemTypeOptions: undefined,
+      // 閮ㄩ棬鍚嶇О
+      itemTypeName: undefined,
+      defaultProps: {
+        children: "children",
+        label: "label"
+      },
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        itemCode: undefined,
+        itemName: undefined,
+        itemTypeId: 0,
+        typeL: 1,
+      },
+      // 鍒椾俊鎭�
+      columns: [
+        { key: 0, label: `鐗╂枡/浜у搧缂栫爜`, visible: true },
+        { key: 1, label: `鐗╂枡/浜у搧鍚嶇О`, visible: true },
+        { key: 2, label: `瑙勬牸鍨嬪彿`, visible: true },
+        { key: 3, label: `鍗曚綅`, visible: true },
+        { key: 4, label: `鐗╂枡/浜у搧`, visible: true },
+        { key: 5, label: `鐗╂枡鍒嗙被`, visible: true },
+        { key: 6, label: `鍒涘缓鏃堕棿`, visible: true }
+      ]
+    };
+  },
+  watch: {
+    // 鏍规嵁鍚嶇О绛涢�夊垎绫绘爲
+    itemTypeName(val) {
+      this.$refs.tree.filter(val);
+    }
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 鏌ヨ鐗╂枡缂栫爜鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listMaterial(this.queryParams).then(response => {
+          this.itemList = response.rows;
+          this.total = response.total;
+          this.loading = false;
+        }
+      );
+    },
+    // 绛涢�夎妭鐐�
+    filterNode(value, data) {
+      if (!value) return true;
+      return data.label.indexOf(value) !== -1;
+    },
+    // 鑺傜偣鍗曞嚮浜嬩欢
+    handleNodeClick(data) {
+      this.queryParams.itemTypeId = data.id;
+      this.handleQuery();
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    handleCurrent(row){
+      if(row){
+        this.selectedRows = row;
+      }
+    },
+    handleRowDbClick(row){
+      if(row){
+        this.selectedRows = row;
+        this.$emit('onSelected',this.selectedRows);
+        this.showFlag = false;
+      }
+    },
+    // 鍗曢�夐�変腑鏁版嵁
+    handleRowChange(row) {
+      debugger;
+      if(row){
+        this.selectedRows = row;
+      }
+    },
+    //纭畾閫変腑
+    confirmSelect(){
+      if(this.selectedItemId ==null || this.selectedItemId==0){
+        this.$notify({
+          title:'鎻愮ず',
+          type:'warning',
+          message: '璇疯嚦灏戦�夋嫨涓�鏉℃暟鎹�!'
+        });
+        return;
+      }
+      console.log(this.selectedRows)
+
+      this.$emit('onSelected',this.selectedRows);
+      this.showFlag = false;
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/directive/dialog/drag.js b/jcdm-ui/src/directive/dialog/drag.js
new file mode 100644
index 0000000..5e357cd
--- /dev/null
+++ b/jcdm-ui/src/directive/dialog/drag.js
@@ -0,0 +1,64 @@
+/**
+* v-dialogDrag 寮圭獥鎷栨嫿
+* Copyright (c) 2019 jcdm
+*/
+
+export default {
+  bind(el, binding, vnode, oldVnode) {
+    const value = binding.value
+    if (value == false) return
+    // 鑾峰彇鎷栨嫿鍐呭澶撮儴
+    const dialogHeaderEl = el.querySelector('.el-dialog__header');
+    const dragDom = el.querySelector('.el-dialog');
+    dialogHeaderEl.style.cursor = 'move';
+    // 鑾峰彇鍘熸湁灞炴�� ie dom鍏冪礌.currentStyle 鐏嫄璋锋瓕 window.getComputedStyle(dom鍏冪礌, null);
+    const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null);
+    dragDom.style.position = 'absolute';
+    dragDom.style.marginTop = 0;
+    let width = dragDom.style.width;
+    if (width.includes('%')) {
+      width = +document.body.clientWidth * (+width.replace(/\%/g, '') / 100);
+    } else {
+      width = +width.replace(/\px/g, '');
+    }
+    dragDom.style.left = `${(document.body.clientWidth - width) / 2}px`;
+    // 榧犳爣鎸変笅浜嬩欢
+    dialogHeaderEl.onmousedown = (e) => {
+      // 榧犳爣鎸変笅锛岃绠楀綋鍓嶅厓绱犺窛绂诲彲瑙嗗尯鐨勮窛绂� (榧犳爣鐐瑰嚮浣嶇疆璺濈鍙绐楀彛鐨勮窛绂�)
+      const disX = e.clientX - dialogHeaderEl.offsetLeft;
+      const disY = e.clientY - dialogHeaderEl.offsetTop;
+
+      // 鑾峰彇鍒扮殑鍊煎甫px 姝e垯鍖归厤鏇挎崲
+      let styL, styT;
+
+      // 娉ㄦ剰鍦╥e涓� 绗竴娆¤幏鍙栧埌鐨勫�间负缁勪欢鑷甫50% 绉诲姩涔嬪悗璧嬪�间负px
+      if (sty.left.includes('%')) {
+        styL = +document.body.clientWidth * (+sty.left.replace(/\%/g, '') / 100);
+        styT = +document.body.clientHeight * (+sty.top.replace(/\%/g, '') / 100);
+      } else {
+        styL = +sty.left.replace(/\px/g, '');
+        styT = +sty.top.replace(/\px/g, '');
+      };
+
+      // 榧犳爣鎷栨嫿浜嬩欢
+      document.onmousemove = function (e) {
+        // 閫氳繃浜嬩欢濮旀墭锛岃绠楃Щ鍔ㄧ殑璺濈 锛堝紑濮嬫嫋鎷借嚦缁撴潫鎷栨嫿鐨勮窛绂伙級
+        const l = e.clientX - disX;
+        const t = e.clientY - disY;
+
+        let finallyL = l + styL
+        let finallyT = t + styT
+
+        // 绉诲姩褰撳墠鍏冪礌
+        dragDom.style.left = `${finallyL}px`;
+        dragDom.style.top = `${finallyT}px`;
+
+      };
+
+      document.onmouseup = function (e) {
+        document.onmousemove = null;
+        document.onmouseup = null;
+      };
+    }
+  }
+};
diff --git a/jcdm-ui/src/directive/dialog/dragHeight.js b/jcdm-ui/src/directive/dialog/dragHeight.js
new file mode 100644
index 0000000..48524e1
--- /dev/null
+++ b/jcdm-ui/src/directive/dialog/dragHeight.js
@@ -0,0 +1,34 @@
+/**
+ * v-dialogDragWidth 鍙嫋鍔ㄥ脊绐楅珮搴︼紙鍙充笅瑙掞級
+ * Copyright (c) 2019 jcdm
+ */
+
+export default {
+  bind(el) {
+    const dragDom = el.querySelector('.el-dialog');
+    const lineEl = document.createElement('div');
+    lineEl.style = 'width: 6px; background: inherit; height: 10px; position: absolute; right: 0; bottom: 0; margin: auto; z-index: 1; cursor: nwse-resize;';
+    lineEl.addEventListener('mousedown',
+      function(e) {
+        // 榧犳爣鎸変笅锛岃绠楀綋鍓嶅厓绱犺窛绂诲彲瑙嗗尯鐨勮窛绂�
+        const disX = e.clientX - el.offsetLeft;
+        const disY = e.clientY - el.offsetTop;
+        // 褰撳墠瀹藉害 楂樺害
+        const curWidth = dragDom.offsetWidth;
+        const curHeight = dragDom.offsetHeight;
+        document.onmousemove = function(e) {
+          e.preventDefault(); // 绉诲姩鏃剁鐢ㄩ粯璁や簨浠�
+          // 閫氳繃浜嬩欢濮旀墭锛岃绠楃Щ鍔ㄧ殑璺濈
+          const xl = e.clientX - disX;
+          const yl = e.clientY - disY
+          dragDom.style.width = `${curWidth + xl}px`;
+          dragDom.style.height = `${curHeight + yl}px`;
+        };
+        document.onmouseup = function(e) {
+          document.onmousemove = null;
+          document.onmouseup = null;
+        };
+      }, false);
+    dragDom.appendChild(lineEl);
+  }
+}
diff --git a/jcdm-ui/src/directive/dialog/dragWidth.js b/jcdm-ui/src/directive/dialog/dragWidth.js
new file mode 100644
index 0000000..16f5e22
--- /dev/null
+++ b/jcdm-ui/src/directive/dialog/dragWidth.js
@@ -0,0 +1,29 @@
+/**
+ * v-dialogDragWidth 鍙嫋鍔ㄥ脊绐楀搴︼紙鍙充晶杈癸級
+ */
+
+export default {
+  bind(el) {
+    const dragDom = el.querySelector('.el-dialog');
+    const lineEl = document.createElement('div');
+    lineEl.style = 'width: 5px; background: inherit; height: 80%; position: absolute; right: 0; top: 0; bottom: 0; margin: auto; z-index: 1; cursor: w-resize;';
+    lineEl.addEventListener('mousedown',
+      function (e) {
+        // 榧犳爣鎸変笅锛岃绠楀綋鍓嶅厓绱犺窛绂诲彲瑙嗗尯鐨勮窛绂�
+        const disX = e.clientX - el.offsetLeft;
+        // 褰撳墠瀹藉害
+        const curWidth = dragDom.offsetWidth;
+        document.onmousemove = function (e) {
+          e.preventDefault(); // 绉诲姩鏃剁鐢ㄩ粯璁や簨浠�
+          // 閫氳繃浜嬩欢濮旀墭锛岃绠楃Щ鍔ㄧ殑璺濈
+          const l = e.clientX - disX;
+          dragDom.style.width = `${curWidth + l}px`;
+        };
+        document.onmouseup = function (e) {
+          document.onmousemove = null;
+          document.onmouseup = null;
+        };
+      }, false);
+    dragDom.appendChild(lineEl);
+  }
+}
diff --git a/jcdm-ui/src/directive/index.js b/jcdm-ui/src/directive/index.js
new file mode 100644
index 0000000..b9b07da
--- /dev/null
+++ b/jcdm-ui/src/directive/index.js
@@ -0,0 +1,23 @@
+import hasRole from './permission/hasRole'
+import hasPermi from './permission/hasPermi'
+import dialogDrag from './dialog/drag'
+import dialogDragWidth from './dialog/dragWidth'
+import dialogDragHeight from './dialog/dragHeight'
+import clipboard from './module/clipboard'
+
+const install = function(Vue) {
+  Vue.directive('hasRole', hasRole)
+  Vue.directive('hasPermi', hasPermi)
+  Vue.directive('clipboard', clipboard)
+  Vue.directive('dialogDrag', dialogDrag)
+  Vue.directive('dialogDragWidth', dialogDragWidth)
+  Vue.directive('dialogDragHeight', dialogDragHeight)
+}
+
+if (window.Vue) {
+  window['hasRole'] = hasRole
+  window['hasPermi'] = hasPermi
+  Vue.use(install); // eslint-disable-line
+}
+
+export default install
diff --git a/jcdm-ui/src/directive/module/clipboard.js b/jcdm-ui/src/directive/module/clipboard.js
new file mode 100644
index 0000000..a1fc1e3
--- /dev/null
+++ b/jcdm-ui/src/directive/module/clipboard.js
@@ -0,0 +1,54 @@
+/**
+* v-clipboard 鏂囧瓧澶嶅埗鍓创
+* Copyright (c) 2021 jcdm
+*/
+
+import Clipboard from 'clipboard'
+export default {
+  bind(el, binding, vnode) {
+    switch (binding.arg) {
+      case 'success':
+        el._vClipBoard_success = binding.value;
+        break;
+      case 'error':
+        el._vClipBoard_error = binding.value;
+        break;
+      default: {
+        const clipboard = new Clipboard(el, {
+          text: () => binding.value,
+          action: () => binding.arg === 'cut' ? 'cut' : 'copy'
+        });
+        clipboard.on('success', e => {
+          const callback = el._vClipBoard_success;
+          callback && callback(e);
+        });
+        clipboard.on('error', e => {
+          const callback = el._vClipBoard_error;
+          callback && callback(e);
+        });
+        el._vClipBoard = clipboard;
+      }
+    }
+  },
+  update(el, binding) {
+    if (binding.arg === 'success') {
+      el._vClipBoard_success = binding.value;
+    } else if (binding.arg === 'error') {
+      el._vClipBoard_error = binding.value;
+    } else {
+      el._vClipBoard.text = function () { return binding.value; };
+      el._vClipBoard.action = () => binding.arg === 'cut' ? 'cut' : 'copy';
+    }
+  },
+  unbind(el, binding) {
+    if (!el._vClipboard) return
+    if (binding.arg === 'success') {
+      delete el._vClipBoard_success;
+    } else if (binding.arg === 'error') {
+      delete el._vClipBoard_error;
+    } else {
+      el._vClipBoard.destroy();
+      delete el._vClipBoard;
+    }
+  }
+}
diff --git a/jcdm-ui/src/directive/permission/hasPermi.js b/jcdm-ui/src/directive/permission/hasPermi.js
new file mode 100644
index 0000000..7101e3e
--- /dev/null
+++ b/jcdm-ui/src/directive/permission/hasPermi.js
@@ -0,0 +1,28 @@
+ /**
+ * v-hasPermi 鎿嶄綔鏉冮檺澶勭悊
+ * Copyright (c) 2019 ruoyi
+ */
+
+import store from '@/store'
+
+export default {
+  inserted(el, binding, vnode) {
+    const { value } = binding
+    const all_permission = "*:*:*";
+    const permissions = store.getters && store.getters.permissions
+
+    if (value && value instanceof Array && value.length > 0) {
+      const permissionFlag = value
+
+      const hasPermissions = permissions.some(permission => {
+        return all_permission === permission || permissionFlag.includes(permission)
+      })
+
+      if (!hasPermissions) {
+        el.parentNode && el.parentNode.removeChild(el)
+      }
+    } else {
+      throw new Error(`璇疯缃搷浣滄潈闄愭爣绛惧�糮)
+    }
+  }
+}
diff --git a/jcdm-ui/src/directive/permission/hasRole.js b/jcdm-ui/src/directive/permission/hasRole.js
new file mode 100644
index 0000000..ad9d4d7
--- /dev/null
+++ b/jcdm-ui/src/directive/permission/hasRole.js
@@ -0,0 +1,28 @@
+ /**
+ * v-hasRole 瑙掕壊鏉冮檺澶勭悊
+ * Copyright (c) 2019 ruoyi
+ */
+
+import store from '@/store'
+
+export default {
+  inserted(el, binding, vnode) {
+    const { value } = binding
+    const super_admin = "admin";
+    const roles = store.getters && store.getters.roles
+
+    if (value && value instanceof Array && value.length > 0) {
+      const roleFlag = value
+
+      const hasRole = roles.some(role => {
+        return super_admin === role || roleFlag.includes(role)
+      })
+
+      if (!hasRole) {
+        el.parentNode && el.parentNode.removeChild(el)
+      }
+    } else {
+      throw new Error(`璇疯缃鑹叉潈闄愭爣绛惧��"`)
+    }
+  }
+}
diff --git a/jcdm-ui/src/layout/components/AppMain.vue b/jcdm-ui/src/layout/components/AppMain.vue
new file mode 100644
index 0000000..a25c562
--- /dev/null
+++ b/jcdm-ui/src/layout/components/AppMain.vue
@@ -0,0 +1,75 @@
+<template>
+  <section class="app-main">
+    <transition name="fade-transform" mode="out-in">
+      <keep-alive :include="cachedViews">
+        <router-view v-if="!$route.meta.link" :key="key" />
+      </keep-alive>
+    </transition>
+    <iframe-toggle />
+  </section>
+</template>
+
+<script>
+import iframeToggle from "./IframeToggle/index"
+
+export default {
+  name: 'AppMain',
+  components: { iframeToggle },
+  computed: {
+    cachedViews() {
+      return this.$store.state.tagsView.cachedViews
+    },
+    key() {
+      return this.$route.path
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.app-main {
+  /* 50= navbar  50  */
+  min-height: calc(100vh - 50px);
+  width: 100%;
+  position: relative;
+  overflow: hidden;
+}
+
+.fixed-header + .app-main {
+  padding-top: 50px;
+}
+
+.hasTagsView {
+  .app-main {
+    /* 84 = navbar + tags-view = 50 + 34 */
+    min-height: calc(100vh - 84px);
+  }
+
+  .fixed-header + .app-main {
+    padding-top: 84px;
+  }
+}
+</style>
+
+<style lang="scss">
+// fix css style bug in open el-dialog
+.el-popup-parent--hidden {
+  .fixed-header {
+    padding-right: 6px;
+  }
+}
+
+::-webkit-scrollbar {
+  width: 6px;
+  height: 6px;
+}
+
+::-webkit-scrollbar-track {
+  background-color: #f1f1f1;
+}
+
+::-webkit-scrollbar-thumb {
+  background-color: #c0c0c0;
+  border-radius: 3px;
+}
+</style>
diff --git a/jcdm-ui/src/layout/components/IframeToggle/index.vue b/jcdm-ui/src/layout/components/IframeToggle/index.vue
new file mode 100644
index 0000000..39ad15b
--- /dev/null
+++ b/jcdm-ui/src/layout/components/IframeToggle/index.vue
@@ -0,0 +1,33 @@
+<template>
+  <transition-group name="fade-transform" mode="out-in">
+    <inner-link
+      v-for="(item, index) in iframeViews"
+      :key="item.path"
+      :iframeId="'iframe' + index"
+      v-show="$route.path === item.path"
+      :src="iframeUrl(item.meta.link, item.query)"
+    ></inner-link>
+  </transition-group>
+</template>
+
+<script>
+import InnerLink from "../InnerLink/index";
+
+export default {
+  components: { InnerLink },
+  computed: {
+    iframeViews() {
+      return this.$store.state.tagsView.iframeViews;
+    }
+  },
+  methods: {
+    iframeUrl(url, query) {
+      if (Object.keys(query).length > 0) {
+        let params = Object.keys(query).map((key) => key + "=" + query[key]).join("&");
+        return url + "?" + params;
+      }
+      return url;
+    }
+  }
+}
+</script>
diff --git a/jcdm-ui/src/layout/components/InnerLink/index.vue b/jcdm-ui/src/layout/components/InnerLink/index.vue
new file mode 100644
index 0000000..badefc5
--- /dev/null
+++ b/jcdm-ui/src/layout/components/InnerLink/index.vue
@@ -0,0 +1,47 @@
+<template>
+  <div :style="'height:' + height" v-loading="loading" element-loading-text="姝e湪鍔犺浇椤甸潰锛岃绋嶅�欙紒">
+    <iframe
+      :id="iframeId"
+      style="width: 100%; height: 100%"
+      :src="src"
+      frameborder="no"
+    ></iframe>
+  </div>
+</template>
+
+<script>
+export default {
+  props: {
+    src: {
+      type: String,
+      default: "/"
+    },
+    iframeId: {
+      type: String
+    }
+  },
+  data() {
+    return {
+      loading: false,
+      height: document.documentElement.clientHeight - 94.5 + "px;"
+    };
+  },
+  mounted() {
+    var _this = this;
+    const iframeId = ("#" + this.iframeId).replace(/\//g, "\\/");
+    const iframe = document.querySelector(iframeId);
+    // iframe椤甸潰loading鎺у埗
+    if (iframe.attachEvent) {
+      this.loading = true;
+      iframe.attachEvent("onload", function () {
+        _this.loading = false;
+      });
+    } else {
+      this.loading = true;
+      iframe.onload = function () {
+        _this.loading = false;
+      };
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/layout/components/Navbar.vue b/jcdm-ui/src/layout/components/Navbar.vue
new file mode 100644
index 0000000..e501a0b
--- /dev/null
+++ b/jcdm-ui/src/layout/components/Navbar.vue
@@ -0,0 +1,192 @@
+<template>
+  <div class="navbar">
+    <hamburger id="hamburger-container" :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
+
+    <breadcrumb id="breadcrumb-container" class="breadcrumb-container" v-if="!topNav"/>
+    <top-nav id="topmenu-container" class="topmenu-container" v-if="topNav"/>
+
+    <div class="right-menu">
+      <template v-if="device!=='mobile'">
+        <search id="header-search" class="right-menu-item" />
+
+        <screenfull id="screenfull" class="right-menu-item hover-effect" />
+
+        <el-tooltip content="甯冨眬澶у皬" effect="dark" placement="bottom">
+          <size-select id="size-select" class="right-menu-item hover-effect" />
+        </el-tooltip>
+
+      </template>
+
+      <el-dropdown class="avatar-container right-menu-item hover-effect" trigger="click">
+        <div class="avatar-wrapper">
+          <img :src="avatar" class="user-avatar">
+          <i class="el-icon-caret-bottom" />
+        </div>
+        <el-dropdown-menu slot="dropdown">
+          <router-link to="/user/profile">
+            <el-dropdown-item>涓汉涓績</el-dropdown-item>
+          </router-link>
+          <el-dropdown-item @click.native="setting = true">
+            <span>甯冨眬璁剧疆</span>
+          </el-dropdown-item>
+          <el-dropdown-item divided @click.native="logout">
+            <span>閫�鍑虹櫥褰�</span>
+          </el-dropdown-item>
+        </el-dropdown-menu>
+      </el-dropdown>
+    </div>
+  </div>
+</template>
+
+<script>
+import { mapGetters } from 'vuex'
+import Breadcrumb from '@/components/Breadcrumb'
+import TopNav from '@/components/TopNav'
+import Hamburger from '@/components/Hamburger'
+import Screenfull from '@/components/Screenfull'
+import SizeSelect from '@/components/SizeSelect'
+import Search from '@/components/HeaderSearch'
+import RuoYiGit from '@/components/RuoYi/Git'
+import RuoYiDoc from '@/components/RuoYi/Doc'
+
+export default {
+  components: {
+    Breadcrumb,
+    TopNav,
+    Hamburger,
+    Screenfull,
+    SizeSelect,
+    Search,
+    RuoYiGit,
+    RuoYiDoc
+  },
+  computed: {
+    ...mapGetters([
+      'sidebar',
+      'avatar',
+      'device'
+    ]),
+    setting: {
+      get() {
+        return this.$store.state.settings.showSettings
+      },
+      set(val) {
+        this.$store.dispatch('settings/changeSetting', {
+          key: 'showSettings',
+          value: val
+        })
+      }
+    },
+    topNav: {
+      get() {
+        return this.$store.state.settings.topNav
+      }
+    }
+  },
+  methods: {
+    toggleSideBar() {
+      this.$store.dispatch('app/toggleSideBar')
+    },
+    async logout() {
+      this.$confirm('纭畾娉ㄩ攢骞堕��鍑虹郴缁熷悧锛�', '鎻愮ず', {
+        confirmButtonText: '纭畾',
+        cancelButtonText: '鍙栨秷',
+        type: 'warning'
+      }).then(() => {
+        this.$store.dispatch('LogOut').then(() => {
+          location.href = '/index';
+        })
+      }).catch(() => {});
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.navbar {
+  height: 50px;
+  overflow: hidden;
+  position: relative;
+  background: #fff;
+  box-shadow: 0 1px 4px rgba(0,21,41,.08);
+
+  .hamburger-container {
+    line-height: 46px;
+    height: 100%;
+    float: left;
+    cursor: pointer;
+    transition: background .3s;
+    -webkit-tap-highlight-color:transparent;
+
+    &:hover {
+      background: rgba(0, 0, 0, .025)
+    }
+  }
+
+  .breadcrumb-container {
+    float: left;
+  }
+
+  .topmenu-container {
+    position: absolute;
+    left: 50px;
+  }
+
+  .errLog-container {
+    display: inline-block;
+    vertical-align: top;
+  }
+
+  .right-menu {
+    float: right;
+    height: 100%;
+    line-height: 50px;
+
+    &:focus {
+      outline: none;
+    }
+
+    .right-menu-item {
+      display: inline-block;
+      padding: 0 8px;
+      height: 100%;
+      font-size: 18px;
+      color: #5a5e66;
+      vertical-align: text-bottom;
+
+      &.hover-effect {
+        cursor: pointer;
+        transition: background .3s;
+
+        &:hover {
+          background: rgba(0, 0, 0, .025)
+        }
+      }
+    }
+
+    .avatar-container {
+      margin-right: 30px;
+
+      .avatar-wrapper {
+        margin-top: 5px;
+        position: relative;
+
+        .user-avatar {
+          cursor: pointer;
+          width: 40px;
+          height: 40px;
+          border-radius: 10px;
+        }
+
+        .el-icon-caret-bottom {
+          cursor: pointer;
+          position: absolute;
+          right: -20px;
+          top: 25px;
+          font-size: 12px;
+        }
+      }
+    }
+  }
+}
+</style>
diff --git a/jcdm-ui/src/layout/components/Settings/index.vue b/jcdm-ui/src/layout/components/Settings/index.vue
new file mode 100644
index 0000000..bb3c9ce
--- /dev/null
+++ b/jcdm-ui/src/layout/components/Settings/index.vue
@@ -0,0 +1,260 @@
+<template>
+  <el-drawer size="280px" :visible="visible" :with-header="false" :append-to-body="true" :show-close="false">
+    <div class="drawer-container">
+      <div>
+        <div class="setting-drawer-content">
+          <div class="setting-drawer-title">
+            <h3 class="drawer-title">涓婚椋庢牸璁剧疆</h3>
+          </div>
+          <div class="setting-drawer-block-checbox">
+            <div class="setting-drawer-block-checbox-item" @click="handleTheme('theme-dark')">
+              <img src="@/assets/images/dark.svg" alt="dark">
+              <div v-if="sideTheme === 'theme-dark'" class="setting-drawer-block-checbox-selectIcon" style="display: block;">
+                <i aria-label="鍥炬爣: check" class="anticon anticon-check">
+                  <svg viewBox="64 64 896 896" data-icon="check" width="1em" height="1em" :fill="theme" aria-hidden="true" focusable="false" class="">
+                    <path d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 0 0-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z"/>
+                  </svg>
+                </i>
+              </div>
+            </div>
+            <div class="setting-drawer-block-checbox-item" @click="handleTheme('theme-light')">
+              <img src="@/assets/images/light.svg" alt="light">
+              <div v-if="sideTheme === 'theme-light'" class="setting-drawer-block-checbox-selectIcon" style="display: block;">
+                <i aria-label="鍥炬爣: check" class="anticon anticon-check">
+                  <svg viewBox="64 64 896 896" data-icon="check" width="1em" height="1em" :fill="theme" aria-hidden="true" focusable="false" class="">
+                    <path d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 0 0-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z"/>
+                  </svg>
+                </i>
+              </div>
+            </div>
+          </div>
+
+          <div class="drawer-item">
+            <span>涓婚棰滆壊</span>
+            <theme-picker style="float: right;height: 26px;margin: -3px 8px 0 0;" @change="themeChange" />
+          </div>
+        </div>
+
+        <el-divider/>
+
+        <h3 class="drawer-title">绯荤粺甯冨眬閰嶇疆</h3>
+
+        <div class="drawer-item">
+          <span>寮�鍚� TopNav</span>
+          <el-switch v-model="topNav" class="drawer-switch" />
+        </div>
+
+        <div class="drawer-item">
+          <span>寮�鍚� Tags-Views</span>
+          <el-switch v-model="tagsView" class="drawer-switch" />
+        </div>
+
+        <div class="drawer-item">
+          <span>鍥哄畾 Header</span>
+          <el-switch v-model="fixedHeader" class="drawer-switch" />
+        </div>
+
+        <div class="drawer-item">
+          <span>鏄剧ず Logo</span>
+          <el-switch v-model="sidebarLogo" class="drawer-switch" />
+        </div>
+
+        <div class="drawer-item">
+          <span>鍔ㄦ�佹爣棰�</span>
+          <el-switch v-model="dynamicTitle" class="drawer-switch" />
+        </div>
+
+        <el-divider/>
+
+        <el-button size="small" type="primary" plain icon="el-icon-document-add" @click="saveSetting">淇濆瓨閰嶇疆</el-button>
+        <el-button size="small" plain icon="el-icon-refresh" @click="resetSetting">閲嶇疆閰嶇疆</el-button>
+      </div>
+    </div>
+  </el-drawer>
+</template>
+
+<script>
+import ThemePicker from '@/components/ThemePicker'
+
+export default {
+  components: { ThemePicker },
+  data() {
+    return {
+      theme: this.$store.state.settings.theme,
+      sideTheme: this.$store.state.settings.sideTheme
+    };
+  },
+  computed: {
+    visible: {
+      get() {
+        return this.$store.state.settings.showSettings
+      }
+    },
+    fixedHeader: {
+      get() {
+        return this.$store.state.settings.fixedHeader
+      },
+      set(val) {
+        this.$store.dispatch('settings/changeSetting', {
+          key: 'fixedHeader',
+          value: val
+        })
+      }
+    },
+    topNav: {
+      get() {
+        return this.$store.state.settings.topNav
+      },
+      set(val) {
+        this.$store.dispatch('settings/changeSetting', {
+          key: 'topNav',
+          value: val
+        })
+        if (!val) {
+          this.$store.dispatch('app/toggleSideBarHide', false);
+          this.$store.commit("SET_SIDEBAR_ROUTERS", this.$store.state.permission.defaultRoutes);
+        }
+      }
+    },
+    tagsView: {
+      get() {
+        return this.$store.state.settings.tagsView
+      },
+      set(val) {
+        this.$store.dispatch('settings/changeSetting', {
+          key: 'tagsView',
+          value: val
+        })
+      }
+    },
+    sidebarLogo: {
+      get() {
+        return this.$store.state.settings.sidebarLogo
+      },
+      set(val) {
+        this.$store.dispatch('settings/changeSetting', {
+          key: 'sidebarLogo',
+          value: val
+        })
+      }
+    },
+    dynamicTitle: {
+      get() {
+        return this.$store.state.settings.dynamicTitle
+      },
+      set(val) {
+        this.$store.dispatch('settings/changeSetting', {
+          key: 'dynamicTitle',
+          value: val
+        })
+      }
+    },
+  },
+  methods: {
+    themeChange(val) {
+      this.$store.dispatch('settings/changeSetting', {
+        key: 'theme',
+        value: val
+      })
+      this.theme = val;
+    },
+    handleTheme(val) {
+      this.$store.dispatch('settings/changeSetting', {
+        key: 'sideTheme',
+        value: val
+      })
+      this.sideTheme = val;
+    },
+    saveSetting() {
+      this.$modal.loading("姝e湪淇濆瓨鍒版湰鍦帮紝璇风◢鍊�...");
+      this.$cache.local.set(
+        "layout-setting",
+        `{
+            "topNav":${this.topNav},
+            "tagsView":${this.tagsView},
+            "fixedHeader":${this.fixedHeader},
+            "sidebarLogo":${this.sidebarLogo},
+            "dynamicTitle":${this.dynamicTitle},
+            "sideTheme":"${this.sideTheme}",
+            "theme":"${this.theme}"
+          }`
+      );
+      setTimeout(this.$modal.closeLoading(), 1000)
+    },
+    resetSetting() {
+      this.$modal.loading("姝e湪娓呴櫎璁剧疆缂撳瓨骞跺埛鏂帮紝璇风◢鍊�...");
+      this.$cache.local.remove("layout-setting")
+      setTimeout("window.location.reload()", 1000)
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+  .setting-drawer-content {
+    .setting-drawer-title {
+      margin-bottom: 12px;
+      color: rgba(0, 0, 0, .85);
+      font-size: 14px;
+      line-height: 22px;
+      font-weight: bold;
+    }
+
+    .setting-drawer-block-checbox {
+      display: flex;
+      justify-content: flex-start;
+      align-items: center;
+      margin-top: 10px;
+      margin-bottom: 20px;
+
+      .setting-drawer-block-checbox-item {
+        position: relative;
+        margin-right: 16px;
+        border-radius: 2px;
+        cursor: pointer;
+
+        img {
+          width: 48px;
+          height: 48px;
+        }
+
+        .setting-drawer-block-checbox-selectIcon {
+          position: absolute;
+          top: 0;
+          right: 0;
+          width: 100%;
+          height: 100%;
+          padding-top: 15px;
+          padding-left: 24px;
+          color: #1890ff;
+          font-weight: 700;
+          font-size: 14px;
+        }
+      }
+    }
+  }
+
+  .drawer-container {
+    padding: 20px;
+    font-size: 14px;
+    line-height: 1.5;
+    word-wrap: break-word;
+
+    .drawer-title {
+      margin-bottom: 12px;
+      color: rgba(0, 0, 0, .85);
+      font-size: 14px;
+      line-height: 22px;
+    }
+
+    .drawer-item {
+      color: rgba(0, 0, 0, .65);
+      font-size: 14px;
+      padding: 12px 0;
+    }
+
+    .drawer-switch {
+      float: right
+    }
+  }
+</style>
diff --git a/jcdm-ui/src/layout/components/Sidebar/FixiOSBug.js b/jcdm-ui/src/layout/components/Sidebar/FixiOSBug.js
new file mode 100644
index 0000000..6823726
--- /dev/null
+++ b/jcdm-ui/src/layout/components/Sidebar/FixiOSBug.js
@@ -0,0 +1,25 @@
+export default {
+  computed: {
+    device() {
+      return this.$store.state.app.device
+    }
+  },
+  mounted() {
+    // In order to fix the click on menu on the ios device will trigger the mouseleave bug
+    this.fixBugIniOS()
+  },
+  methods: {
+    fixBugIniOS() {
+      const $subMenu = this.$refs.subMenu
+      if ($subMenu) {
+        const handleMouseleave = $subMenu.handleMouseleave
+        $subMenu.handleMouseleave = (e) => {
+          if (this.device === 'mobile') {
+            return
+          }
+          handleMouseleave(e)
+        }
+      }
+    }
+  }
+}
diff --git a/jcdm-ui/src/layout/components/Sidebar/Item.vue b/jcdm-ui/src/layout/components/Sidebar/Item.vue
new file mode 100644
index 0000000..be3285d
--- /dev/null
+++ b/jcdm-ui/src/layout/components/Sidebar/Item.vue
@@ -0,0 +1,33 @@
+<script>
+export default {
+  name: 'MenuItem',
+  functional: true,
+  props: {
+    icon: {
+      type: String,
+      default: ''
+    },
+    title: {
+      type: String,
+      default: ''
+    }
+  },
+  render(h, context) {
+    const { icon, title } = context.props
+    const vnodes = []
+
+    if (icon) {
+      vnodes.push(<svg-icon icon-class={icon}/>)
+    }
+
+    if (title) {
+      if (title.length > 5) {
+        vnodes.push(<span slot='title' title={(title)}>{(title)}</span>)
+      } else {
+        vnodes.push(<span slot='title'>{(title)}</span>)
+      }
+    }
+    return vnodes
+  }
+}
+</script>
diff --git a/jcdm-ui/src/layout/components/Sidebar/Link.vue b/jcdm-ui/src/layout/components/Sidebar/Link.vue
new file mode 100644
index 0000000..8b0bc93
--- /dev/null
+++ b/jcdm-ui/src/layout/components/Sidebar/Link.vue
@@ -0,0 +1,43 @@
+<template>
+  <component :is="type" v-bind="linkProps(to)">
+    <slot />
+  </component>
+</template>
+
+<script>
+import { isExternal } from '@/utils/validate'
+
+export default {
+  props: {
+    to: {
+      type: [String, Object],
+      required: true
+    }
+  },
+  computed: {
+    isExternal() {
+      return isExternal(this.to)
+    },
+    type() {
+      if (this.isExternal) {
+        return 'a'
+      }
+      return 'router-link'
+    }
+  },
+  methods: {
+    linkProps(to) {
+      if (this.isExternal) {
+        return {
+          href: to,
+          target: '_blank',
+          rel: 'noopener'
+        }
+      }
+      return {
+        to: to
+      }
+    }
+  }
+}
+</script>
diff --git a/jcdm-ui/src/layout/components/Sidebar/Logo.vue b/jcdm-ui/src/layout/components/Sidebar/Logo.vue
new file mode 100644
index 0000000..2774cc8
--- /dev/null
+++ b/jcdm-ui/src/layout/components/Sidebar/Logo.vue
@@ -0,0 +1,93 @@
+<template>
+  <div class="sidebar-logo-container" :class="{'collapse':collapse}" :style="{ backgroundColor: sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground }">
+    <transition name="sidebarLogoFade">
+      <router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/">
+        <img v-if="logo" :src="logo" class="sidebar-logo" />
+        <h1 v-else class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">{{ title }} </h1>
+      </router-link>
+      <router-link v-else key="expand" class="sidebar-logo-link" to="/">
+        <img v-if="logo" :src="logo" class="sidebar-logo" />
+        <h1 class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">{{ title }} </h1>
+      </router-link>
+    </transition>
+  </div>
+</template>
+
+<script>
+import logoImg from '@/assets/logo/logo.png'
+import variables from '@/assets/styles/variables.scss'
+
+export default {
+  name: 'SidebarLogo',
+  props: {
+    collapse: {
+      type: Boolean,
+      required: true
+    }
+  },
+  computed: {
+    variables() {
+      return variables;
+    },
+    sideTheme() {
+      return this.$store.state.settings.sideTheme
+    }
+  },
+  data() {
+    return {
+      title: process.env.VUE_APP_TITLE,
+      logo: logoImg
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.sidebarLogoFade-enter-active {
+  transition: opacity 1.5s;
+}
+
+.sidebarLogoFade-enter,
+.sidebarLogoFade-leave-to {
+  opacity: 0;
+}
+
+.sidebar-logo-container {
+  position: relative;
+  width: 100%;
+  height: 50px;
+  line-height: 50px;
+  background: #2b2f3a;
+  text-align: center;
+  overflow: hidden;
+
+  & .sidebar-logo-link {
+    height: 100%;
+    width: 100%;
+
+    & .sidebar-logo {
+      width: 32px;
+      height: 32px;
+      vertical-align: middle;
+      margin-right: 12px;
+    }
+
+    & .sidebar-title {
+      display: inline-block;
+      margin: 0;
+      color: #fff;
+      font-weight: 600;
+      line-height: 50px;
+      font-size: 14px;
+      font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif;
+      vertical-align: middle;
+    }
+  }
+
+  &.collapse {
+    .sidebar-logo {
+      margin-right: 0px;
+    }
+  }
+}
+</style>
diff --git a/jcdm-ui/src/layout/components/Sidebar/SidebarItem.vue b/jcdm-ui/src/layout/components/Sidebar/SidebarItem.vue
new file mode 100644
index 0000000..82ba407
--- /dev/null
+++ b/jcdm-ui/src/layout/components/Sidebar/SidebarItem.vue
@@ -0,0 +1,100 @@
+<template>
+  <div v-if="!item.hidden">
+    <template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow">
+      <app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path, onlyOneChild.query)">
+        <el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">
+          <item :icon="onlyOneChild.meta.icon||(item.meta&&item.meta.icon)" :title="onlyOneChild.meta.title" />
+        </el-menu-item>
+      </app-link>
+    </template>
+
+    <el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>
+      <template slot="title">
+        <item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="item.meta.title" />
+      </template>
+      <sidebar-item
+        v-for="(child, index) in item.children"
+        :key="child.path + index"
+        :is-nest="true"
+        :item="child"
+        :base-path="resolvePath(child.path)"
+        class="nest-menu"
+      />
+    </el-submenu>
+  </div>
+</template>
+
+<script>
+import path from 'path'
+import { isExternal } from '@/utils/validate'
+import Item from './Item'
+import AppLink from './Link'
+import FixiOSBug from './FixiOSBug'
+
+export default {
+  name: 'SidebarItem',
+  components: { Item, AppLink },
+  mixins: [FixiOSBug],
+  props: {
+    // route object
+    item: {
+      type: Object,
+      required: true
+    },
+    isNest: {
+      type: Boolean,
+      default: false
+    },
+    basePath: {
+      type: String,
+      default: ''
+    }
+  },
+  data() {
+    this.onlyOneChild = null
+    return {}
+  },
+  methods: {
+    hasOneShowingChild(children = [], parent) {
+      if (!children) {
+        children = [];
+      }
+      const showingChildren = children.filter(item => {
+        if (item.hidden) {
+          return false
+        } else {
+          // Temp set(will be used if only has one showing child)
+          this.onlyOneChild = item
+          return true
+        }
+      })
+
+      // When there is only one child router, the child router is displayed by default
+      if (showingChildren.length === 1) {
+        return true
+      }
+
+      // Show parent if there are no child router to display
+      if (showingChildren.length === 0) {
+        this.onlyOneChild = { ... parent, path: '', noShowingChildren: true }
+        return true
+      }
+
+      return false
+    },
+    resolvePath(routePath, routeQuery) {
+      if (isExternal(routePath)) {
+        return routePath
+      }
+      if (isExternal(this.basePath)) {
+        return this.basePath
+      }
+      if (routeQuery) {
+        let query = JSON.parse(routeQuery);
+        return { path: path.resolve(this.basePath, routePath), query: query }
+      }
+      return path.resolve(this.basePath, routePath)
+    }
+  }
+}
+</script>
diff --git a/jcdm-ui/src/layout/components/Sidebar/index.vue b/jcdm-ui/src/layout/components/Sidebar/index.vue
new file mode 100644
index 0000000..51d0839
--- /dev/null
+++ b/jcdm-ui/src/layout/components/Sidebar/index.vue
@@ -0,0 +1,57 @@
+<template>
+    <div :class="{'has-logo':showLogo}" :style="{ backgroundColor: settings.sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground }">
+        <logo v-if="showLogo" :collapse="isCollapse" />
+        <el-scrollbar :class="settings.sideTheme" wrap-class="scrollbar-wrapper">
+            <el-menu
+                :default-active="activeMenu"
+                :collapse="isCollapse"
+                :background-color="settings.sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground"
+                :text-color="settings.sideTheme === 'theme-dark' ? variables.menuColor : variables.menuLightColor"
+                :unique-opened="true"
+                :active-text-color="settings.theme"
+                :collapse-transition="false"
+                mode="vertical"
+            >
+                <sidebar-item
+                    v-for="(route, index) in sidebarRouters"
+                    :key="route.path  + index"
+                    :item="route"
+                    :base-path="route.path"
+                />
+            </el-menu>
+        </el-scrollbar>
+    </div>
+</template>
+
+<script>
+import { mapGetters, mapState } from "vuex";
+import Logo from "./Logo";
+import SidebarItem from "./SidebarItem";
+import variables from "@/assets/styles/variables.scss";
+
+export default {
+    components: { SidebarItem, Logo },
+    computed: {
+        ...mapState(["settings"]),
+        ...mapGetters(["sidebarRouters", "sidebar"]),
+        activeMenu() {
+            const route = this.$route;
+            const { meta, path } = route;
+            // if set path, the sidebar will highlight the path you set
+            if (meta.activeMenu) {
+                return meta.activeMenu;
+            }
+            return path;
+        },
+        showLogo() {
+            return this.$store.state.settings.sidebarLogo;
+        },
+        variables() {
+            return variables;
+        },
+        isCollapse() {
+            return !this.sidebar.opened;
+        }
+    }
+};
+</script>
diff --git a/jcdm-ui/src/layout/components/TagsView/ScrollPane.vue b/jcdm-ui/src/layout/components/TagsView/ScrollPane.vue
new file mode 100644
index 0000000..bb753a1
--- /dev/null
+++ b/jcdm-ui/src/layout/components/TagsView/ScrollPane.vue
@@ -0,0 +1,94 @@
+<template>
+  <el-scrollbar ref="scrollContainer" :vertical="false" class="scroll-container" @wheel.native.prevent="handleScroll">
+    <slot />
+  </el-scrollbar>
+</template>
+
+<script>
+const tagAndTagSpacing = 4 // tagAndTagSpacing
+
+export default {
+  name: 'ScrollPane',
+  data() {
+    return {
+      left: 0
+    }
+  },
+  computed: {
+    scrollWrapper() {
+      return this.$refs.scrollContainer.$refs.wrap
+    }
+  },
+  mounted() {
+    this.scrollWrapper.addEventListener('scroll', this.emitScroll, true)
+  },
+  beforeDestroy() {
+    this.scrollWrapper.removeEventListener('scroll', this.emitScroll)
+  },
+  methods: {
+    handleScroll(e) {
+      const eventDelta = e.wheelDelta || -e.deltaY * 40
+      const $scrollWrapper = this.scrollWrapper
+      $scrollWrapper.scrollLeft = $scrollWrapper.scrollLeft + eventDelta / 4
+    },
+    emitScroll() {
+      this.$emit('scroll')
+    },
+    moveToTarget(currentTag) {
+      const $container = this.$refs.scrollContainer.$el
+      const $containerWidth = $container.offsetWidth
+      const $scrollWrapper = this.scrollWrapper
+      const tagList = this.$parent.$refs.tag
+
+      let firstTag = null
+      let lastTag = null
+
+      // find first tag and last tag
+      if (tagList.length > 0) {
+        firstTag = tagList[0]
+        lastTag = tagList[tagList.length - 1]
+      }
+
+      if (firstTag === currentTag) {
+        $scrollWrapper.scrollLeft = 0
+      } else if (lastTag === currentTag) {
+        $scrollWrapper.scrollLeft = $scrollWrapper.scrollWidth - $containerWidth
+      } else {
+        // find preTag and nextTag
+        const currentIndex = tagList.findIndex(item => item === currentTag)
+        const prevTag = tagList[currentIndex - 1]
+        const nextTag = tagList[currentIndex + 1]
+
+        // the tag's offsetLeft after of nextTag
+        const afterNextTagOffsetLeft = nextTag.$el.offsetLeft + nextTag.$el.offsetWidth + tagAndTagSpacing
+
+        // the tag's offsetLeft before of prevTag
+        const beforePrevTagOffsetLeft = prevTag.$el.offsetLeft - tagAndTagSpacing
+
+        if (afterNextTagOffsetLeft > $scrollWrapper.scrollLeft + $containerWidth) {
+          $scrollWrapper.scrollLeft = afterNextTagOffsetLeft - $containerWidth
+        } else if (beforePrevTagOffsetLeft < $scrollWrapper.scrollLeft) {
+          $scrollWrapper.scrollLeft = beforePrevTagOffsetLeft
+        }
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.scroll-container {
+  white-space: nowrap;
+  position: relative;
+  overflow: hidden;
+  width: 100%;
+  ::v-deep {
+    .el-scrollbar__bar {
+      bottom: 0px;
+    }
+    .el-scrollbar__wrap {
+      height: 49px;
+    }
+  }
+}
+</style>
diff --git a/jcdm-ui/src/layout/components/TagsView/index.vue b/jcdm-ui/src/layout/components/TagsView/index.vue
new file mode 100644
index 0000000..96585a5
--- /dev/null
+++ b/jcdm-ui/src/layout/components/TagsView/index.vue
@@ -0,0 +1,332 @@
+<template>
+  <div id="tags-view-container" class="tags-view-container">
+    <scroll-pane ref="scrollPane" class="tags-view-wrapper" @scroll="handleScroll">
+      <router-link
+        v-for="tag in visitedViews"
+        ref="tag"
+        :key="tag.path"
+        :class="isActive(tag)?'active':''"
+        :to="{ path: tag.path, query: tag.query, fullPath: tag.fullPath }"
+        tag="span"
+        class="tags-view-item"
+        :style="activeStyle(tag)"
+        @click.middle.native="!isAffix(tag)?closeSelectedTag(tag):''"
+        @contextmenu.prevent.native="openMenu(tag,$event)"
+      >
+        {{ tag.title }}
+        <span v-if="!isAffix(tag)" class="el-icon-close" @click.prevent.stop="closeSelectedTag(tag)" />
+      </router-link>
+    </scroll-pane>
+    <ul v-show="visible" :style="{left:left+'px',top:top+'px'}" class="contextmenu">
+      <li @click="refreshSelectedTag(selectedTag)"><i class="el-icon-refresh-right"></i> 鍒锋柊椤甸潰</li>
+      <li v-if="!isAffix(selectedTag)" @click="closeSelectedTag(selectedTag)"><i class="el-icon-close"></i> 鍏抽棴褰撳墠</li>
+      <li @click="closeOthersTags"><i class="el-icon-circle-close"></i> 鍏抽棴鍏朵粬</li>
+      <li v-if="!isFirstView()" @click="closeLeftTags"><i class="el-icon-back"></i> 鍏抽棴宸︿晶</li>
+      <li v-if="!isLastView()" @click="closeRightTags"><i class="el-icon-right"></i> 鍏抽棴鍙充晶</li>
+      <li @click="closeAllTags(selectedTag)"><i class="el-icon-circle-close"></i> 鍏ㄩ儴鍏抽棴</li>
+    </ul>
+  </div>
+</template>
+
+<script>
+import ScrollPane from './ScrollPane'
+import path from 'path'
+
+export default {
+  components: { ScrollPane },
+  data() {
+    return {
+      visible: false,
+      top: 0,
+      left: 0,
+      selectedTag: {},
+      affixTags: []
+    }
+  },
+  computed: {
+    visitedViews() {
+      return this.$store.state.tagsView.visitedViews
+    },
+    routes() {
+      return this.$store.state.permission.routes
+    },
+    theme() {
+      return this.$store.state.settings.theme;
+    }
+  },
+  watch: {
+    $route() {
+      this.addTags()
+      this.moveToCurrentTag()
+    },
+    visible(value) {
+      if (value) {
+        document.body.addEventListener('click', this.closeMenu)
+      } else {
+        document.body.removeEventListener('click', this.closeMenu)
+      }
+    }
+  },
+  mounted() {
+    this.initTags()
+    this.addTags()
+  },
+  methods: {
+    isActive(route) {
+      return route.path === this.$route.path
+    },
+    activeStyle(tag) {
+      if (!this.isActive(tag)) return {};
+      return {
+        "background-color": this.theme,
+        "border-color": this.theme
+      };
+    },
+    isAffix(tag) {
+      return tag.meta && tag.meta.affix
+    },
+    isFirstView() {
+      try {
+        return this.selectedTag.fullPath === '/index' || this.selectedTag.fullPath === this.visitedViews[1].fullPath
+      } catch (err) {
+        return false
+      }
+    },
+    isLastView() {
+      try {
+        return this.selectedTag.fullPath === this.visitedViews[this.visitedViews.length - 1].fullPath
+      } catch (err) {
+        return false
+      }
+    },
+    filterAffixTags(routes, basePath = '/') {
+      let tags = []
+      routes.forEach(route => {
+        if (route.meta && route.meta.affix) {
+          const tagPath = path.resolve(basePath, route.path)
+          tags.push({
+            fullPath: tagPath,
+            path: tagPath,
+            name: route.name,
+            meta: { ...route.meta }
+          })
+        }
+        if (route.children) {
+          const tempTags = this.filterAffixTags(route.children, route.path)
+          if (tempTags.length >= 1) {
+            tags = [...tags, ...tempTags]
+          }
+        }
+      })
+      return tags
+    },
+    initTags() {
+      const affixTags = this.affixTags = this.filterAffixTags(this.routes)
+      for (const tag of affixTags) {
+        // Must have tag name
+        if (tag.name) {
+          this.$store.dispatch('tagsView/addVisitedView', tag)
+        }
+      }
+    },
+    addTags() {
+      const { name } = this.$route
+      if (name) {
+        this.$store.dispatch('tagsView/addView', this.$route)
+        if (this.$route.meta.link) {
+          this.$store.dispatch('tagsView/addIframeView', this.$route)
+        }
+      }
+      return false
+    },
+    moveToCurrentTag() {
+      const tags = this.$refs.tag
+      this.$nextTick(() => {
+        for (const tag of tags) {
+          if (tag.to.path === this.$route.path) {
+            this.$refs.scrollPane.moveToTarget(tag)
+            // when query is different then update
+            if (tag.to.fullPath !== this.$route.fullPath) {
+              this.$store.dispatch('tagsView/updateVisitedView', this.$route)
+            }
+            break
+          }
+        }
+      })
+    },
+    refreshSelectedTag(view) {
+      this.$tab.refreshPage(view);
+      if (this.$route.meta.link) {
+        this.$store.dispatch('tagsView/delIframeView', this.$route)
+      }
+    },
+    closeSelectedTag(view) {
+      this.$tab.closePage(view).then(({ visitedViews }) => {
+        if (this.isActive(view)) {
+          this.toLastView(visitedViews, view)
+        }
+      })
+    },
+    closeRightTags() {
+      this.$tab.closeRightPage(this.selectedTag).then(visitedViews => {
+        if (!visitedViews.find(i => i.fullPath === this.$route.fullPath)) {
+          this.toLastView(visitedViews)
+        }
+      })
+    },
+    closeLeftTags() {
+      this.$tab.closeLeftPage(this.selectedTag).then(visitedViews => {
+        if (!visitedViews.find(i => i.fullPath === this.$route.fullPath)) {
+          this.toLastView(visitedViews)
+        }
+      })
+    },
+    closeOthersTags() {
+      this.$router.push(this.selectedTag.fullPath).catch(()=>{});
+      this.$tab.closeOtherPage(this.selectedTag).then(() => {
+        this.moveToCurrentTag()
+      })
+    },
+    closeAllTags(view) {
+      this.$tab.closeAllPage().then(({ visitedViews }) => {
+        if (this.affixTags.some(tag => tag.path === this.$route.path)) {
+          return
+        }
+        this.toLastView(visitedViews, view)
+      })
+    },
+    toLastView(visitedViews, view) {
+      const latestView = visitedViews.slice(-1)[0]
+      if (latestView) {
+        this.$router.push(latestView.fullPath)
+      } else {
+        // now the default is to redirect to the home page if there is no tags-view,
+        // you can adjust it according to your needs.
+        if (view.name === 'Dashboard') {
+          // to reload home page
+          this.$router.replace({ path: '/redirect' + view.fullPath })
+        } else {
+          this.$router.push('/')
+        }
+      }
+    },
+    openMenu(tag, e) {
+      const menuMinWidth = 105
+      const offsetLeft = this.$el.getBoundingClientRect().left // container margin left
+      const offsetWidth = this.$el.offsetWidth // container width
+      const maxLeft = offsetWidth - menuMinWidth // left boundary
+      const left = e.clientX - offsetLeft + 15 // 15: margin right
+
+      if (left > maxLeft) {
+        this.left = maxLeft
+      } else {
+        this.left = left
+      }
+
+      this.top = e.clientY
+      this.visible = true
+      this.selectedTag = tag
+    },
+    closeMenu() {
+      this.visible = false
+    },
+    handleScroll() {
+      this.closeMenu()
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.tags-view-container {
+  height: 34px;
+  width: 100%;
+  background: #fff;
+  border-bottom: 1px solid #d8dce5;
+  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .12), 0 0 3px 0 rgba(0, 0, 0, .04);
+  .tags-view-wrapper {
+    .tags-view-item {
+      display: inline-block;
+      position: relative;
+      cursor: pointer;
+      height: 26px;
+      line-height: 26px;
+      border: 1px solid #d8dce5;
+      color: #495060;
+      background: #fff;
+      padding: 0 8px;
+      font-size: 12px;
+      margin-left: 5px;
+      margin-top: 4px;
+      &:first-of-type {
+        margin-left: 15px;
+      }
+      &:last-of-type {
+        margin-right: 15px;
+      }
+      &.active {
+        background-color: #42b983;
+        color: #fff;
+        border-color: #42b983;
+        &::before {
+          content: '';
+          background: #fff;
+          display: inline-block;
+          width: 8px;
+          height: 8px;
+          border-radius: 50%;
+          position: relative;
+          margin-right: 2px;
+        }
+      }
+    }
+  }
+  .contextmenu {
+    margin: 0;
+    background: #fff;
+    z-index: 3000;
+    position: absolute;
+    list-style-type: none;
+    padding: 5px 0;
+    border-radius: 4px;
+    font-size: 12px;
+    font-weight: 400;
+    color: #333;
+    box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, .3);
+    li {
+      margin: 0;
+      padding: 7px 16px;
+      cursor: pointer;
+      &:hover {
+        background: #eee;
+      }
+    }
+  }
+}
+</style>
+
+<style lang="scss">
+//reset element css of el-icon-close
+.tags-view-wrapper {
+  .tags-view-item {
+    .el-icon-close {
+      width: 16px;
+      height: 16px;
+      vertical-align: 2px;
+      border-radius: 50%;
+      text-align: center;
+      transition: all .3s cubic-bezier(.645, .045, .355, 1);
+      transform-origin: 100% 50%;
+      &:before {
+        transform: scale(.6);
+        display: inline-block;
+        vertical-align: -3px;
+      }
+      &:hover {
+        background-color: #b4bccc;
+        color: #fff;
+      }
+    }
+  }
+}
+</style>
diff --git a/jcdm-ui/src/layout/components/index.js b/jcdm-ui/src/layout/components/index.js
new file mode 100644
index 0000000..104bd3a
--- /dev/null
+++ b/jcdm-ui/src/layout/components/index.js
@@ -0,0 +1,5 @@
+export { default as AppMain } from './AppMain'
+export { default as Navbar } from './Navbar'
+export { default as Settings } from './Settings'
+export { default as Sidebar } from './Sidebar/index.vue'
+export { default as TagsView } from './TagsView/index.vue'
diff --git a/jcdm-ui/src/layout/index.vue b/jcdm-ui/src/layout/index.vue
new file mode 100644
index 0000000..dba4393
--- /dev/null
+++ b/jcdm-ui/src/layout/index.vue
@@ -0,0 +1,111 @@
+<template>
+  <div :class="classObj" class="app-wrapper" :style="{'--current-color': theme}">
+    <div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside"/>
+    <sidebar v-if="!sidebar.hide" class="sidebar-container"/>
+    <div :class="{hasTagsView:needTagsView,sidebarHide:sidebar.hide}" class="main-container">
+      <div :class="{'fixed-header':fixedHeader}">
+        <navbar/>
+        <tags-view v-if="needTagsView"/>
+      </div>
+      <app-main/>
+      <right-panel>
+        <settings/>
+      </right-panel>
+    </div>
+  </div>
+</template>
+
+<script>
+import RightPanel from '@/components/RightPanel'
+import { AppMain, Navbar, Settings, Sidebar, TagsView } from './components'
+import ResizeMixin from './mixin/ResizeHandler'
+import { mapState } from 'vuex'
+import variables from '@/assets/styles/variables.scss'
+
+export default {
+  name: 'Layout',
+  components: {
+    AppMain,
+    Navbar,
+    RightPanel,
+    Settings,
+    Sidebar,
+    TagsView
+  },
+  mixins: [ResizeMixin],
+  computed: {
+    ...mapState({
+      theme: state => state.settings.theme,
+      sideTheme: state => state.settings.sideTheme,
+      sidebar: state => state.app.sidebar,
+      device: state => state.app.device,
+      needTagsView: state => state.settings.tagsView,
+      fixedHeader: state => state.settings.fixedHeader
+    }),
+    classObj() {
+      return {
+        hideSidebar: !this.sidebar.opened,
+        openSidebar: this.sidebar.opened,
+        withoutAnimation: this.sidebar.withoutAnimation,
+        mobile: this.device === 'mobile'
+      }
+    },
+    variables() {
+      return variables;
+    }
+  },
+  methods: {
+    handleClickOutside() {
+      this.$store.dispatch('app/closeSideBar', { withoutAnimation: false })
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+  @import "~@/assets/styles/mixin.scss";
+  @import "~@/assets/styles/variables.scss";
+
+  .app-wrapper {
+    @include clearfix;
+    position: relative;
+    height: 100%;
+    width: 100%;
+
+    &.mobile.openSidebar {
+      position: fixed;
+      top: 0;
+    }
+  }
+
+  .drawer-bg {
+    background: #000;
+    opacity: 0.3;
+    width: 100%;
+    top: 0;
+    height: 100%;
+    position: absolute;
+    z-index: 999;
+  }
+
+  .fixed-header {
+    position: fixed;
+    top: 0;
+    right: 0;
+    z-index: 9;
+    width: calc(100% - #{$base-sidebar-width});
+    transition: width 0.28s;
+  }
+
+  .hideSidebar .fixed-header {
+    width: calc(100% - 54px);
+  }
+
+  .sidebarHide .fixed-header {
+    width: 100%;
+  }
+
+  .mobile .fixed-header {
+    width: 100%;
+  }
+</style>
diff --git a/jcdm-ui/src/layout/mixin/ResizeHandler.js b/jcdm-ui/src/layout/mixin/ResizeHandler.js
new file mode 100644
index 0000000..e8d0df8
--- /dev/null
+++ b/jcdm-ui/src/layout/mixin/ResizeHandler.js
@@ -0,0 +1,45 @@
+import store from '@/store'
+
+const { body } = document
+const WIDTH = 992 // refer to Bootstrap's responsive design
+
+export default {
+  watch: {
+    $route(route) {
+      if (this.device === 'mobile' && this.sidebar.opened) {
+        store.dispatch('app/closeSideBar', { withoutAnimation: false })
+      }
+    }
+  },
+  beforeMount() {
+    window.addEventListener('resize', this.$_resizeHandler)
+  },
+  beforeDestroy() {
+    window.removeEventListener('resize', this.$_resizeHandler)
+  },
+  mounted() {
+    const isMobile = this.$_isMobile()
+    if (isMobile) {
+      store.dispatch('app/toggleDevice', 'mobile')
+      store.dispatch('app/closeSideBar', { withoutAnimation: true })
+    }
+  },
+  methods: {
+    // use $_ for mixins properties
+    // https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential
+    $_isMobile() {
+      const rect = body.getBoundingClientRect()
+      return rect.width - 1 < WIDTH
+    },
+    $_resizeHandler() {
+      if (!document.hidden) {
+        const isMobile = this.$_isMobile()
+        store.dispatch('app/toggleDevice', isMobile ? 'mobile' : 'desktop')
+
+        if (isMobile) {
+          store.dispatch('app/closeSideBar', { withoutAnimation: true })
+        }
+      }
+    }
+  }
+}
diff --git a/jcdm-ui/src/main.js b/jcdm-ui/src/main.js
new file mode 100644
index 0000000..aea3622
--- /dev/null
+++ b/jcdm-ui/src/main.js
@@ -0,0 +1,103 @@
+import Vue from 'vue'
+
+import Cookies from 'js-cookie'
+
+import Element from 'element-ui'
+import './assets/styles/element-variables.scss'
+
+import '@/assets/styles/index.scss' // global css
+import '@/assets/styles/ruoyi.scss' // ruoyi css
+import App from './App'
+import store from './store'
+import router from './router'
+import directive from './directive' // directive
+import plugins from './plugins' // plugins
+import { download } from '@/utils/request'
+
+import './assets/icons' // icon
+import './permission' // permission control
+import { getDicts } from "@/api/system/dict/data";
+import { getConfigKey } from "@/api/system/config";
+import { parseTime, resetForm, addDateRange, selectDictLabel, selectDictLabels, handleTree } from "@/utils/ruoyi";
+// 鍒嗛〉缁勪欢
+import Pagination from "@/components/Pagination";
+// 鑷畾涔夎〃鏍煎伐鍏风粍浠�
+import RightToolbar from "@/components/RightToolbar"
+// 瀵屾枃鏈粍浠�
+import Editor from "@/components/Editor"
+// 鏂囦欢涓婁紶缁勪欢
+import FileUpload from "@/components/FileUpload"
+// 鍥剧墖涓婁紶缁勪欢
+import ImageUpload from "@/components/ImageUpload"
+// 鍥剧墖棰勮缁勪欢
+import ImagePreview from "@/components/ImagePreview"
+// 瀛楀吀鏍囩缁勪欢
+import DictTag from '@/components/DictTag'
+// 澶撮儴鏍囩缁勪欢
+import VueMeta from 'vue-meta'
+// 瀛楀吀鏁版嵁缁勪欢
+import DictData from '@/components/DictData'
+import './router/directives.js';
+
+// 鍏ㄥ眬鏂规硶鎸傝浇
+Vue.prototype.getDicts = getDicts
+Vue.prototype.getConfigKey = getConfigKey
+Vue.prototype.parseTime = parseTime
+Vue.prototype.resetForm = resetForm
+Vue.prototype.addDateRange = addDateRange
+Vue.prototype.selectDictLabel = selectDictLabel
+Vue.prototype.selectDictLabels = selectDictLabels
+Vue.prototype.download = download
+Vue.prototype.handleTree = handleTree
+
+// 鍏ㄥ眬缁勪欢鎸傝浇
+Vue.component('DictTag', DictTag)
+Vue.component('Pagination', Pagination)
+Vue.component('RightToolbar', RightToolbar)
+Vue.component('Editor', Editor)
+Vue.component('FileUpload', FileUpload)
+Vue.component('ImageUpload', ImageUpload)
+Vue.component('ImagePreview', ImagePreview)
+
+Vue.use(directive)
+Vue.use(plugins)
+Vue.use(VueMeta)
+DictData.install()
+
+/**
+ * If you don't want to use mock-server
+ * you want to use MockJs for mock api
+ * you can execute: mockXHR()
+ *
+ * Currently MockJs will be used in the production environment,
+ * please remove it before going online! ! !
+ */
+
+Vue.use(Element, {
+  size: Cookies.get('size') || 'medium' // set element-ui default size
+})
+
+Vue.config.productionTip = false
+
+new Vue({
+  el: '#app',
+  router,
+  store,
+  render: h => h(App)
+})
+//ip楠岃瘉
+Vue.directive('ipAddressValidator', {
+  bind(el, binding, vnode) {
+    el.addEventListener('input', () => {
+      const value = el.value;
+      // IPv4 address validation
+      if (/^((\d{1,2}|1\d{2}|2[0-4]\d|25[0-5])(\.((\d{1,2}|1\d{2}|2[0-4]\d|25[0-5]))){3})$/.test(value)) {
+        console.log("Valid IPv4 Address");
+      } else if (!/(^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$)|(^(?:(?:[\x00-\x7F]|[\u0391-\uFFEF])+)(?:\.[a-zA-Z0-9]+)*$)/i.test(value)) {
+        console.log("Invalid IPv4 or IPv6 Address");
+      } else {
+        console.log("Valid IPv6 Address");
+      }
+    });
+  },
+});
diff --git a/jcdm-ui/src/permission.js b/jcdm-ui/src/permission.js
new file mode 100644
index 0000000..c568979
--- /dev/null
+++ b/jcdm-ui/src/permission.js
@@ -0,0 +1,58 @@
+import router from './router'
+import store from './store'
+import { Message } from 'element-ui'
+import NProgress from 'nprogress'
+import 'nprogress/nprogress.css'
+import { getToken } from '@/utils/auth'
+import { isRelogin } from '@/utils/request'
+
+NProgress.configure({ showSpinner: false })
+
+const whiteList = ['/login', '/register']
+
+router.beforeEach((to, from, next) => {
+  NProgress.start()
+  if (getToken()) {
+    to.meta.title && store.dispatch('settings/setTitle', to.meta.title)
+    /* has token*/
+    if (to.path === '/login') {
+      next({ path: '/' })
+      NProgress.done()
+    } else if (whiteList.indexOf(to.path) !== -1) {
+      next()
+    } else {
+      if (store.getters.roles.length === 0) {
+        isRelogin.show = true
+        // 鍒ゆ柇褰撳墠鐢ㄦ埛鏄惁宸叉媺鍙栧畬user_info淇℃伅
+        store.dispatch('GetInfo').then(() => {
+          isRelogin.show = false
+          store.dispatch('GenerateRoutes').then(accessRoutes => {
+            // 鏍规嵁roles鏉冮檺鐢熸垚鍙闂殑璺敱琛�
+            router.addRoutes(accessRoutes) // 鍔ㄦ�佹坊鍔犲彲璁块棶璺敱琛�
+            next({ ...to, replace: true }) // hack鏂规硶 纭繚addRoutes宸插畬鎴�
+          })
+        }).catch(err => {
+            store.dispatch('LogOut').then(() => {
+              Message.error(err)
+              next({ path: '/' })
+            })
+          })
+      } else {
+        next()
+      }
+    }
+  } else {
+    // 娌℃湁token
+    if (whiteList.indexOf(to.path) !== -1) {
+      // 鍦ㄥ厤鐧诲綍鐧藉悕鍗曪紝鐩存帴杩涘叆
+      next()
+    } else {
+      next(`/login?redirect=${encodeURIComponent(to.fullPath)}`) // 鍚﹀垯鍏ㄩ儴閲嶅畾鍚戝埌鐧诲綍椤�
+      NProgress.done()
+    }
+  }
+})
+
+router.afterEach(() => {
+  NProgress.done()
+})
diff --git a/jcdm-ui/src/plugins/auth.js b/jcdm-ui/src/plugins/auth.js
new file mode 100644
index 0000000..6c6bc24
--- /dev/null
+++ b/jcdm-ui/src/plugins/auth.js
@@ -0,0 +1,60 @@
+import store from '@/store'
+
+function authPermission(permission) {
+  const all_permission = "*:*:*";
+  const permissions = store.getters && store.getters.permissions
+  if (permission && permission.length > 0) {
+    return permissions.some(v => {
+      return all_permission === v || v === permission
+    })
+  } else {
+    return false
+  }
+}
+
+function authRole(role) {
+  const super_admin = "admin";
+  const roles = store.getters && store.getters.roles
+  if (role && role.length > 0) {
+    return roles.some(v => {
+      return super_admin === v || v === role
+    })
+  } else {
+    return false
+  }
+}
+
+export default {
+  // 楠岃瘉鐢ㄦ埛鏄惁鍏峰鏌愭潈闄�
+  hasPermi(permission) {
+    return authPermission(permission);
+  },
+  // 楠岃瘉鐢ㄦ埛鏄惁鍚湁鎸囧畾鏉冮檺锛屽彧闇�鍖呭惈鍏朵腑涓�涓�
+  hasPermiOr(permissions) {
+    return permissions.some(item => {
+      return authPermission(item)
+    })
+  },
+  // 楠岃瘉鐢ㄦ埛鏄惁鍚湁鎸囧畾鏉冮檺锛屽繀椤诲叏閮ㄦ嫢鏈�
+  hasPermiAnd(permissions) {
+    return permissions.every(item => {
+      return authPermission(item)
+    })
+  },
+  // 楠岃瘉鐢ㄦ埛鏄惁鍏峰鏌愯鑹�
+  hasRole(role) {
+    return authRole(role);
+  },
+  // 楠岃瘉鐢ㄦ埛鏄惁鍚湁鎸囧畾瑙掕壊锛屽彧闇�鍖呭惈鍏朵腑涓�涓�
+  hasRoleOr(roles) {
+    return roles.some(item => {
+      return authRole(item)
+    })
+  },
+  // 楠岃瘉鐢ㄦ埛鏄惁鍚湁鎸囧畾瑙掕壊锛屽繀椤诲叏閮ㄦ嫢鏈�
+  hasRoleAnd(roles) {
+    return roles.every(item => {
+      return authRole(item)
+    })
+  }
+}
diff --git a/jcdm-ui/src/plugins/cache.js b/jcdm-ui/src/plugins/cache.js
new file mode 100644
index 0000000..6b5c00b
--- /dev/null
+++ b/jcdm-ui/src/plugins/cache.js
@@ -0,0 +1,77 @@
+const sessionCache = {
+  set (key, value) {
+    if (!sessionStorage) {
+      return
+    }
+    if (key != null && value != null) {
+      sessionStorage.setItem(key, value)
+    }
+  },
+  get (key) {
+    if (!sessionStorage) {
+      return null
+    }
+    if (key == null) {
+      return null
+    }
+    return sessionStorage.getItem(key)
+  },
+  setJSON (key, jsonValue) {
+    if (jsonValue != null) {
+      this.set(key, JSON.stringify(jsonValue))
+    }
+  },
+  getJSON (key) {
+    const value = this.get(key)
+    if (value != null) {
+      return JSON.parse(value)
+    }
+  },
+  remove (key) {
+    sessionStorage.removeItem(key);
+  }
+}
+const localCache = {
+  set (key, value) {
+    if (!localStorage) {
+      return
+    }
+    if (key != null && value != null) {
+      localStorage.setItem(key, value)
+    }
+  },
+  get (key) {
+    if (!localStorage) {
+      return null
+    }
+    if (key == null) {
+      return null
+    }
+    return localStorage.getItem(key)
+  },
+  setJSON (key, jsonValue) {
+    if (jsonValue != null) {
+      this.set(key, JSON.stringify(jsonValue))
+    }
+  },
+  getJSON (key) {
+    const value = this.get(key)
+    if (value != null) {
+      return JSON.parse(value)
+    }
+  },
+  remove (key) {
+    localStorage.removeItem(key);
+  }
+}
+
+export default {
+  /**
+   * 浼氳瘽绾х紦瀛�
+   */
+  session: sessionCache,
+  /**
+   * 鏈湴缂撳瓨
+   */
+  local: localCache
+}
diff --git a/jcdm-ui/src/plugins/download.js b/jcdm-ui/src/plugins/download.js
new file mode 100644
index 0000000..42acd00
--- /dev/null
+++ b/jcdm-ui/src/plugins/download.js
@@ -0,0 +1,79 @@
+import axios from 'axios'
+import {Loading, Message} from 'element-ui'
+import { saveAs } from 'file-saver'
+import { getToken } from '@/utils/auth'
+import errorCode from '@/utils/errorCode'
+import { blobValidate } from "@/utils/ruoyi";
+
+const baseURL = process.env.VUE_APP_BASE_API
+let downloadLoadingInstance;
+
+export default {
+  name(name, isDelete = true) {
+    var url = baseURL + "/common/download?fileName=" + encodeURIComponent(name) + "&delete=" + isDelete
+    axios({
+      method: 'get',
+      url: url,
+      responseType: 'blob',
+      headers: { 'Authorization': 'Bearer ' + getToken() }
+    }).then((res) => {
+      const isBlob = blobValidate(res.data);
+      if (isBlob) {
+        const blob = new Blob([res.data])
+        this.saveAs(blob, decodeURIComponent(res.headers['download-filename']))
+      } else {
+        this.printErrMsg(res.data);
+      }
+    })
+  },
+  resource(resource) {
+    var url = baseURL + "/common/download/resource?resource=" + encodeURIComponent(resource);
+    axios({
+      method: 'get',
+      url: url,
+      responseType: 'blob',
+      headers: { 'Authorization': 'Bearer ' + getToken() }
+    }).then((res) => {
+      const isBlob = blobValidate(res.data);
+      if (isBlob) {
+        const blob = new Blob([res.data])
+        this.saveAs(blob, decodeURIComponent(res.headers['download-filename']))
+      } else {
+        this.printErrMsg(res.data);
+      }
+    })
+  },
+  zip(url, name) {
+    var url = baseURL + url
+    downloadLoadingInstance = Loading.service({ text: "姝e湪涓嬭浇鏁版嵁锛岃绋嶅��", spinner: "el-icon-loading", background: "rgba(0, 0, 0, 0.7)", })
+    axios({
+      method: 'get',
+      url: url,
+      responseType: 'blob',
+      headers: { 'Authorization': 'Bearer ' + getToken() }
+    }).then((res) => {
+      const isBlob = blobValidate(res.data);
+      if (isBlob) {
+        const blob = new Blob([res.data], { type: 'application/zip' })
+        this.saveAs(blob, name)
+      } else {
+        this.printErrMsg(res.data);
+      }
+      downloadLoadingInstance.close();
+    }).catch((r) => {
+      console.error(r)
+      Message.error('涓嬭浇鏂囦欢鍑虹幇閿欒锛岃鑱旂郴绠$悊鍛橈紒')
+      downloadLoadingInstance.close();
+    })
+  },
+  saveAs(text, name, opts) {
+    saveAs(text, name, opts);
+  },
+  async printErrMsg(data) {
+    const resText = await data.text();
+    const rspObj = JSON.parse(resText);
+    const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']
+    Message.error(errMsg);
+  }
+}
+
diff --git a/jcdm-ui/src/plugins/index.js b/jcdm-ui/src/plugins/index.js
new file mode 100644
index 0000000..d000f2d
--- /dev/null
+++ b/jcdm-ui/src/plugins/index.js
@@ -0,0 +1,20 @@
+import tab from './tab'
+import auth from './auth'
+import cache from './cache'
+import modal from './modal'
+import download from './download'
+
+export default {
+  install(Vue) {
+    // 椤电鎿嶄綔
+    Vue.prototype.$tab = tab
+    // 璁よ瘉瀵硅薄
+    Vue.prototype.$auth = auth
+    // 缂撳瓨瀵硅薄
+    Vue.prototype.$cache = cache
+    // 妯℃�佹瀵硅薄
+    Vue.prototype.$modal = modal
+    // 涓嬭浇鏂囦欢
+    Vue.prototype.$download = download
+  }
+}
diff --git a/jcdm-ui/src/plugins/modal.js b/jcdm-ui/src/plugins/modal.js
new file mode 100644
index 0000000..b37ca14
--- /dev/null
+++ b/jcdm-ui/src/plugins/modal.js
@@ -0,0 +1,83 @@
+import { Message, MessageBox, Notification, Loading } from 'element-ui'
+
+let loadingInstance;
+
+export default {
+  // 娑堟伅鎻愮ず
+  msg(content) {
+    Message.info(content)
+  },
+  // 閿欒娑堟伅
+  msgError(content) {
+    Message.error(content)
+  },
+  // 鎴愬姛娑堟伅
+  msgSuccess(content) {
+    Message.success(content)
+  },
+  // 璀﹀憡娑堟伅
+  msgWarning(content) {
+    Message.warning(content)
+  },
+  // 寮瑰嚭鎻愮ず
+  alert(content) {
+    MessageBox.alert(content, "绯荤粺鎻愮ず")
+  },
+  // 閿欒鎻愮ず
+  alertError(content) {
+    MessageBox.alert(content, "绯荤粺鎻愮ず", { type: 'error' })
+  },
+  // 鎴愬姛鎻愮ず
+  alertSuccess(content) {
+    MessageBox.alert(content, "绯荤粺鎻愮ず", { type: 'success' })
+  },
+  // 璀﹀憡鎻愮ず
+  alertWarning(content) {
+    MessageBox.alert(content, "绯荤粺鎻愮ず", { type: 'warning' })
+  },
+  // 閫氱煡鎻愮ず
+  notify(content) {
+    Notification.info(content)
+  },
+  // 閿欒閫氱煡
+  notifyError(content) {
+    Notification.error(content);
+  },
+  // 鎴愬姛閫氱煡
+  notifySuccess(content) {
+    Notification.success(content)
+  },
+  // 璀﹀憡閫氱煡
+  notifyWarning(content) {
+    Notification.warning(content)
+  },
+  // 纭绐椾綋
+  confirm(content) {
+    return MessageBox.confirm(content, "绯荤粺鎻愮ず", {
+      confirmButtonText: '纭畾',
+      cancelButtonText: '鍙栨秷',
+      type: "warning",
+    })
+  },
+  // 鎻愪氦鍐呭
+  prompt(content) {
+    return MessageBox.prompt(content, "绯荤粺鎻愮ず", {
+      confirmButtonText: '纭畾',
+      cancelButtonText: '鍙栨秷',
+      type: "warning",
+    })
+  },
+  // 鎵撳紑閬僵灞�
+  loading(content) {
+    loadingInstance = Loading.service({
+      lock: true,
+      text: content,
+      spinner: "el-icon-loading",
+      background: "rgba(0, 0, 0, 0.7)",
+    })
+  },
+  // 鍏抽棴閬僵灞�
+  closeLoading() {
+    loadingInstance.close();
+  }
+}
diff --git a/jcdm-ui/src/plugins/tab.js b/jcdm-ui/src/plugins/tab.js
new file mode 100644
index 0000000..fcde419
--- /dev/null
+++ b/jcdm-ui/src/plugins/tab.js
@@ -0,0 +1,71 @@
+import store from '@/store'
+import router from '@/router';
+
+export default {
+  // 鍒锋柊褰撳墠tab椤电
+  refreshPage(obj) {
+    const { path, query, matched } = router.currentRoute;
+    if (obj === undefined) {
+      matched.forEach((m) => {
+        if (m.components && m.components.default && m.components.default.name) {
+          if (!['Layout', 'ParentView'].includes(m.components.default.name)) {
+            obj = { name: m.components.default.name, path: path, query: query };
+          }
+        }
+      });
+    }
+    return store.dispatch('tagsView/delCachedView', obj).then(() => {
+      const { path, query } = obj
+      router.replace({
+        path: '/redirect' + path,
+        query: query
+      })
+    })
+  },
+  // 鍏抽棴褰撳墠tab椤电锛屾墦寮�鏂伴〉绛�
+  closeOpenPage(obj) {
+    store.dispatch("tagsView/delView", router.currentRoute);
+    if (obj !== undefined) {
+      return router.push(obj);
+    }
+  },
+  // 鍏抽棴鎸囧畾tab椤电
+  closePage(obj) {
+    if (obj === undefined) {
+      return store.dispatch('tagsView/delView', router.currentRoute).then(({ visitedViews }) => {
+        const latestView = visitedViews.slice(-1)[0]
+        if (latestView) {
+          return router.push(latestView.fullPath)
+        }
+        return router.push('/');
+      });
+    }
+    return store.dispatch('tagsView/delView', obj);
+  },
+  // 鍏抽棴鎵�鏈塼ab椤电
+  closeAllPage() {
+    return store.dispatch('tagsView/delAllViews');
+  },
+  // 鍏抽棴宸︿晶tab椤电
+  closeLeftPage(obj) {
+    return store.dispatch('tagsView/delLeftTags', obj || router.currentRoute);
+  },
+  // 鍏抽棴鍙充晶tab椤电
+  closeRightPage(obj) {
+    return store.dispatch('tagsView/delRightTags', obj || router.currentRoute);
+  },
+  // 鍏抽棴鍏朵粬tab椤电
+  closeOtherPage(obj) {
+    return store.dispatch('tagsView/delOthersViews', obj || router.currentRoute);
+  },
+  // 娣诲姞tab椤电
+  openPage(title, url, params) {
+    const obj = { path: url, meta: { title: title } }
+    store.dispatch('tagsView/addView', obj);
+    return router.push({ path: url, query: params });
+  },
+  // 淇敼tab椤电
+  updatePage(obj) {
+    return store.dispatch('tagsView/updateVisitedView', obj);
+  }
+}
diff --git a/jcdm-ui/src/router/directives.js b/jcdm-ui/src/router/directives.js
new file mode 100644
index 0000000..63e695d
--- /dev/null
+++ b/jcdm-ui/src/router/directives.js
@@ -0,0 +1,74 @@
+import Vue from 'vue'
+
+// v-dialogpop-up: 寮圭獥鎷栨嫿
+Vue.directive('dialogpop-up', {
+  bind(el, binding, vnode, oldVnode) {
+    const dialogHeaderEl = el.querySelector('.el-dialog__header')//el-dialog鍜宧eader涔嬮棿鏄袱涓笅鍒掔嚎
+    const dragDom = el.querySelector('.el-dialog')
+    dialogHeaderEl.style.cursor = 'move'
+
+    // 鑾峰彇鍘熸湁灞炴�� ie dom鍏冪礌.currentStyle 鐏嫄璋锋瓕 window.getComputedStyle(dom鍏冪礌, null);
+    const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null)
+
+    dialogHeaderEl.onmousedown = (e) => {
+      // 榧犳爣鎸変笅锛岃绠楀綋鍓嶅厓绱犺窛绂诲彲瑙嗗尯鐨勮窛绂�
+      const disX = e.clientX - dialogHeaderEl.offsetLeft
+      const disY = e.clientY - dialogHeaderEl.offsetTop
+
+      // 鑾峰彇鍒扮殑鍊煎甫px 姝e垯鍖归厤鏇挎崲
+      let styL, styT
+
+      // 娉ㄦ剰鍦╥e涓� 绗竴娆¤幏鍙栧埌鐨勫�间负缁勪欢鑷甫50% 绉诲姩涔嬪悗璧嬪�间负px
+      if (sty.left.includes('%')) {
+        styL = +document.body.clientWidth * (+sty.left.replace(/\%/g, '') / 100)
+        styT = +document.body.clientHeight * (+sty.top.replace(/\%/g, '') / 100)
+      } else {
+        styL = +sty.left.replace(/\px/g, '')
+        styT = +sty.top.replace(/\px/g, '')
+      }
+
+      document.onmousemove = function(e) {
+        // 閫氳繃浜嬩欢濮旀墭锛岃绠楃Щ鍔ㄧ殑璺濈
+        const l = e.clientX - disX
+        const t = e.clientY - disY
+
+        // 绉诲姩褰撳墠鍏冪礌
+        dragDom.style.left = `${l + styL}px`
+        dragDom.style.top = `${t + styT}px`
+
+        // 灏嗘鏃剁殑浣嶇疆浼犲嚭鍘�
+        // binding.value({x:e.pageX,y:e.pageY})
+      }
+
+      document.onmouseup = function(e) {
+        document.onmousemove = null
+        document.onmouseup = null
+      }
+    }
+  }
+})
+
+// v-dialogDragWidth: 寮圭獥瀹藉害鎷栧ぇ 鎷栧皬
+Vue.directive('dialogDragWidth', {
+  bind(el, binding, vnode, oldVnode) {
+    const dragDom = binding.value.$el.querySelector('.el-dialog')
+
+    el.onmousedown = (e) => {
+      // 榧犳爣鎸変笅锛岃绠楀綋鍓嶅厓绱犺窛绂诲彲瑙嗗尯鐨勮窛绂�
+      const disX = e.clientX - el.offsetLeft
+
+      document.onmousemove = function(e) {
+        e.preventDefault() // 绉诲姩鏃剁鐢ㄩ粯璁や簨浠�
+
+        // 閫氳繃浜嬩欢濮旀墭锛岃绠楃Щ鍔ㄧ殑璺濈
+        const l = e.clientX - disX
+        dragDom.style.width = `${l}px`
+      }
+
+      document.onmouseup = function(e) {
+        document.onmousemove = null
+        document.onmouseup = null
+      }
+    }
+  }
+})
diff --git a/jcdm-ui/src/router/index.js b/jcdm-ui/src/router/index.js
new file mode 100644
index 0000000..f1a20fa
--- /dev/null
+++ b/jcdm-ui/src/router/index.js
@@ -0,0 +1,239 @@
+import Vue from 'vue'
+import Router from 'vue-router'
+
+Vue.use(Router)
+
+/* Layout */
+import Layout from '@/layout'
+
+/**
+ * Note: 璺敱閰嶇疆椤�
+ *
+ * hidden: true                     // 褰撹缃� true 鐨勬椂鍊欒璺敱涓嶄細鍐嶄晶杈规爮鍑虹幇 濡�401锛宭ogin绛夐〉闈紝鎴栬�呭涓�浜涚紪杈戦〉闈�/edit/1
+ * alwaysShow: true                 // 褰撲綘涓�涓矾鐢变笅闈㈢殑 children 澹版槑鐨勮矾鐢卞ぇ浜�1涓椂锛岃嚜鍔ㄤ細鍙樻垚宓屽鐨勬ā寮�--濡傜粍浠堕〉闈�
+ *                                  // 鍙湁涓�涓椂锛屼細灏嗛偅涓瓙璺敱褰撳仛鏍硅矾鐢辨樉绀哄湪渚ц竟鏍�--濡傚紩瀵奸〉闈�
+ *                                  // 鑻ヤ綘鎯充笉绠¤矾鐢变笅闈㈢殑 children 澹版槑鐨勪釜鏁伴兘鏄剧ず浣犵殑鏍硅矾鐢�
+ *                                  // 浣犲彲浠ヨ缃� alwaysShow: true锛岃繖鏍峰畠灏变細蹇界暐涔嬪墠瀹氫箟鐨勮鍒欙紝涓�鐩存樉绀烘牴璺敱
+ * redirect: noRedirect             // 褰撹缃� noRedirect 鐨勬椂鍊欒璺敱鍦ㄩ潰鍖呭睉瀵艰埅涓笉鍙鐐瑰嚮
+ * name:'router-name'               // 璁惧畾璺敱鐨勫悕瀛楋紝涓�瀹氳濉啓涓嶇劧浣跨敤<keep-alive>鏃朵細鍑虹幇鍚勭闂
+ * query: '{"id": 1, "name": "ry"}' // 璁块棶璺敱鐨勯粯璁や紶閫掑弬鏁�
+ * roles: ['admin', 'common']       // 璁块棶璺敱鐨勮鑹叉潈闄�
+ * permissions: ['a:a:a', 'b:b:b']  // 璁块棶璺敱鐨勮彍鍗曟潈闄�
+ * meta : {
+    noCache: true                   // 濡傛灉璁剧疆涓簍rue锛屽垯涓嶄細琚� <keep-alive> 缂撳瓨(榛樿 false)
+    title: 'title'                  // 璁剧疆璇ヨ矾鐢卞湪渚ц竟鏍忓拰闈㈠寘灞戜腑灞曠ず鐨勫悕瀛�
+    icon: 'svg-name'                // 璁剧疆璇ヨ矾鐢辩殑鍥炬爣锛屽搴旇矾寰剆rc/assets/icons/svg
+    breadcrumb: false               // 濡傛灉璁剧疆涓篺alse锛屽垯涓嶄細鍦╞readcrumb闈㈠寘灞戜腑鏄剧ず
+    activeMenu: '/system/user'      // 褰撹矾鐢辫缃簡璇ュ睘鎬э紝鍒欎細楂樹寒鐩稿搴旂殑渚ц竟鏍忋��
+  }
+ */
+
+// 鍏叡璺敱
+export const constantRoutes = [
+  {
+    path: '/redirect',
+    component: Layout,
+    hidden: true,
+    children: [
+      {
+        path: '/redirect/:path(.*)',
+        component: () => import('@/views/redirect')
+      }
+    ]
+  },
+  {
+    path: '/login',
+    component: () => import('@/views/login'),
+    hidden: true
+  },
+  {
+    path: '/register',
+    component: () => import('@/views/register'),
+    hidden: true
+  },
+  {
+    path: '/404',
+    component: () => import('@/views/error/404'),
+    hidden: true
+  },
+  {
+    path: '/401',
+    component: () => import('@/views/error/401'),
+    hidden: true
+  },
+  {
+    path: '',
+    component: Layout,
+    redirect: 'index',
+    children: [
+      {
+        path: 'index',
+        component: () => import('@/views/index'),
+        name: 'Index',
+        meta: { title: '棣栭〉', icon: 'dashboard', affix: true }
+      }
+    ]
+  },
+  {
+    path: '/user',
+    component: Layout,
+    hidden: true,
+    redirect: 'noredirect',
+    children: [
+      {
+        path: 'profile',
+        component: () => import('@/views/system/user/profile/index'),
+        name: 'Profile',
+        meta: { title: '涓汉涓績', icon: 'user' }
+      }
+    ]
+  }
+]
+
+// 鍔ㄦ�佽矾鐢憋紝鍩轰簬鐢ㄦ埛鏉冮檺鍔ㄦ�佸幓鍔犺浇
+export const dynamicRoutes = [
+  {
+    path: '/system/user-auth',
+    component: Layout,
+    hidden: true,
+    permissions: ['system:user:edit'],
+    children: [
+      {
+        path: 'role/:userId(\\d+)',
+        component: () => import('@/views/system/user/authRole'),
+        name: 'AuthRole',
+        meta: { title: '鍒嗛厤瑙掕壊', activeMenu: '/system/user' }
+      }
+    ]
+  },
+  {
+    path: '/system/role-auth',
+    component: Layout,
+    hidden: true,
+    permissions: ['system:role:edit'],
+    children: [
+      {
+        path: 'user/:roleId(\\d+)',
+        component: () => import('@/views/system/role/authUser'),
+        name: 'AuthUser',
+        meta: { title: '鍒嗛厤鐢ㄦ埛', activeMenu: '/system/role' }
+      }
+    ]
+  },
+  {
+    path: '/system/dict-data',
+    component: Layout,
+    hidden: true,
+    permissions: ['system:dict:list'],
+    children: [
+      {
+        path: 'index/:dictId(\\d+)',
+        component: () => import('@/views/system/dict/data'),
+        name: 'Data',
+        meta: { title: '瀛楀吀鏁版嵁', activeMenu: '/system/dict' }
+      }
+    ]
+  },
+  {
+    path: '/main/formula-data',
+    component: Layout,
+    hidden: true,
+    permissions: ['bs:formulaChild:list'],
+    children: [
+      {
+        path: 'index',
+        component: () => import('@/views/main/bs/formulaChild/index'),
+        name: 'Data',
+        meta: { title: '閰嶆柟璇︽儏', activeMenu: '/main/bs/formulaChild' }
+      }
+    ]
+  },
+  {
+    path: '/main/route-data',
+    component: Layout,
+    hidden: true,
+    permissions: ['bs:technologyRouteChild:list'],
+    children: [
+      {
+        path: 'index',
+        component: () => import('@/views/main/bs/technologyRouteChild/index'),
+        name: 'Data',
+        meta: { title: '宸ヨ壓娴佺▼璇︽儏', activeMenu: '/main/bs/technologyRouteChild' }
+      }
+    ]
+  },
+  {
+    path: '/main/bom-data',
+    component: Layout,
+    hidden: true,
+    permissions: ['bs:ProductBomChild:list'],
+    children: [
+      {
+        path: 'index',
+        component: () => import('@/views/main/bs/ProductBomChild/index'),
+        name: 'Data',
+        meta: { title: 'BOM瀛愪欢淇℃伅', activeMenu: '/main/bs/ProductBomChild' }
+      }
+    ]
+  },
+  {
+    path: '/monitor/job-log',
+    component: Layout,
+    hidden: true,
+    permissions: ['monitor:job:list'],
+    children: [
+      {
+        path: 'index/:jobId(\\d+)',
+        component: () => import('@/views/monitor/job/log'),
+        name: 'JobLog',
+        meta: { title: '璋冨害鏃ュ織', activeMenu: '/monitor/job' }
+      }
+    ]
+  },
+  {
+    path: '/tool/gen-edit',
+    component: Layout,
+    hidden: true,
+    permissions: ['tool:gen:edit'],
+    children: [
+      {
+        path: 'index/:tableId(\\d+)',
+        component: () => import('@/views/tool/gen/editTable'),
+        name: 'GenEdit',
+        meta: { title: '淇敼鐢熸垚閰嶇疆', activeMenu: '/tool/gen' }
+      }
+    ]
+  },
+  {
+    path: '/main/workReport-data',
+    component: Layout,
+    hidden: true,
+    permissions: ['om:workReport:list'],
+    children: [
+      {
+        path: 'index',
+        component: () => import('@/views/main/om/workReport/index'),
+        name: 'Data',
+        meta: { title: '鎶ュ伐璁板綍琛�', activeMenu: '/main/om/workReport' }
+      }
+    ]
+  },
+]
+
+// 闃叉杩炵画鐐瑰嚮澶氭璺敱鎶ラ敊
+let routerPush = Router.prototype.push;
+let routerReplace = Router.prototype.replace;
+// push
+Router.prototype.push = function push(location) {
+  return routerPush.call(this, location).catch(err => err)
+}
+// replace
+Router.prototype.replace = function push(location) {
+  return routerReplace.call(this, location).catch(err => err)
+}
+
+export default new Router({
+  mode: 'history', // 鍘绘帀url涓殑#
+  scrollBehavior: () => ({ y: 0 }),
+  routes: constantRoutes
+})
diff --git a/jcdm-ui/src/settings.js b/jcdm-ui/src/settings.js
new file mode 100644
index 0000000..6a0b09f
--- /dev/null
+++ b/jcdm-ui/src/settings.js
@@ -0,0 +1,44 @@
+module.exports = {
+  /**
+   * 渚ц竟鏍忎富棰� 娣辫壊涓婚theme-dark锛屾祬鑹蹭富棰榯heme-light
+   */
+  sideTheme: 'theme-dark',
+
+  /**
+   * 鏄惁绯荤粺甯冨眬閰嶇疆
+   */
+  showSettings: false,
+
+  /**
+   * 鏄惁鏄剧ず椤堕儴瀵艰埅
+   */
+  topNav: false,
+
+  /**
+   * 鏄惁鏄剧ず tagsView
+   */
+  tagsView: true,
+
+  /**
+   * 鏄惁鍥哄畾澶撮儴
+   */
+  fixedHeader: false,
+
+  /**
+   * 鏄惁鏄剧ずlogo
+   */
+  sidebarLogo: true,
+
+  /**
+   * 鏄惁鏄剧ず鍔ㄦ�佹爣棰�
+   */
+  dynamicTitle: false,
+
+  /**
+   * @type {string | array} 'production' | ['production', 'development']
+   * @description Need show err logs component.
+   * The default is only used in the production env
+   * If you want to also use it in dev, you can pass ['production', 'development']
+   */
+  errorLog: 'production'
+}
diff --git a/jcdm-ui/src/store/getters.js b/jcdm-ui/src/store/getters.js
new file mode 100644
index 0000000..8adb1b6
--- /dev/null
+++ b/jcdm-ui/src/store/getters.js
@@ -0,0 +1,19 @@
+const getters = {
+  sidebar: state => state.app.sidebar,
+  size: state => state.app.size,
+  device: state => state.app.device,
+  dict: state => state.dict.dict,
+  visitedViews: state => state.tagsView.visitedViews,
+  cachedViews: state => state.tagsView.cachedViews,
+  token: state => state.user.token,
+  avatar: state => state.user.avatar,
+  name: state => state.user.name,
+  introduction: state => state.user.introduction,
+  roles: state => state.user.roles,
+  permissions: state => state.user.permissions,
+  permission_routes: state => state.permission.routes,
+  topbarRouters:state => state.permission.topbarRouters,
+  defaultRoutes:state => state.permission.defaultRoutes,
+  sidebarRouters:state => state.permission.sidebarRouters,
+}
+export default getters
diff --git a/jcdm-ui/src/store/index.js b/jcdm-ui/src/store/index.js
new file mode 100644
index 0000000..97aaef8
--- /dev/null
+++ b/jcdm-ui/src/store/index.js
@@ -0,0 +1,25 @@
+import Vue from 'vue'
+import Vuex from 'vuex'
+import app from './modules/app'
+import dict from './modules/dict'
+import user from './modules/user'
+import tagsView from './modules/tagsView'
+import permission from './modules/permission'
+import settings from './modules/settings'
+import getters from './getters'
+
+Vue.use(Vuex)
+
+const store = new Vuex.Store({
+  modules: {
+    app,
+    dict,
+    user,
+    tagsView,
+    permission,
+    settings
+  },
+  getters
+})
+
+export default store
diff --git a/jcdm-ui/src/store/modules/app.js b/jcdm-ui/src/store/modules/app.js
new file mode 100644
index 0000000..3e22d1c
--- /dev/null
+++ b/jcdm-ui/src/store/modules/app.js
@@ -0,0 +1,66 @@
+import Cookies from 'js-cookie'
+
+const state = {
+  sidebar: {
+    opened: Cookies.get('sidebarStatus') ? !!+Cookies.get('sidebarStatus') : true,
+    withoutAnimation: false,
+    hide: false
+  },
+  device: 'desktop',
+  size: Cookies.get('size') || 'medium'
+}
+
+const mutations = {
+  TOGGLE_SIDEBAR: state => {
+    if (state.sidebar.hide) {
+      return false;
+    }
+    state.sidebar.opened = !state.sidebar.opened
+    state.sidebar.withoutAnimation = false
+    if (state.sidebar.opened) {
+      Cookies.set('sidebarStatus', 1)
+    } else {
+      Cookies.set('sidebarStatus', 0)
+    }
+  },
+  CLOSE_SIDEBAR: (state, withoutAnimation) => {
+    Cookies.set('sidebarStatus', 0)
+    state.sidebar.opened = false
+    state.sidebar.withoutAnimation = withoutAnimation
+  },
+  TOGGLE_DEVICE: (state, device) => {
+    state.device = device
+  },
+  SET_SIZE: (state, size) => {
+    state.size = size
+    Cookies.set('size', size)
+  },
+  SET_SIDEBAR_HIDE: (state, status) => {
+    state.sidebar.hide = status
+  }
+}
+
+const actions = {
+  toggleSideBar({ commit }) {
+    commit('TOGGLE_SIDEBAR')
+  },
+  closeSideBar({ commit }, { withoutAnimation }) {
+    commit('CLOSE_SIDEBAR', withoutAnimation)
+  },
+  toggleDevice({ commit }, device) {
+    commit('TOGGLE_DEVICE', device)
+  },
+  setSize({ commit }, size) {
+    commit('SET_SIZE', size)
+  },
+  toggleSideBarHide({ commit }, status) {
+    commit('SET_SIDEBAR_HIDE', status)
+  }
+}
+
+export default {
+  namespaced: true,
+  state,
+  mutations,
+  actions
+}
diff --git a/jcdm-ui/src/store/modules/dict.js b/jcdm-ui/src/store/modules/dict.js
new file mode 100644
index 0000000..7a1b2f0
--- /dev/null
+++ b/jcdm-ui/src/store/modules/dict.js
@@ -0,0 +1,50 @@
+const state = {
+  dict: new Array()
+}
+const mutations = {
+  SET_DICT: (state, { key, value }) => {
+    if (key !== null && key !== "") {
+      state.dict.push({
+        key: key,
+        value: value
+      })
+    }
+  },
+  REMOVE_DICT: (state, key) => {
+    try {
+      for (let i = 0; i < state.dict.length; i++) {
+        if (state.dict[i].key == key) {
+          state.dict.splice(i, 1)
+          return true
+        }
+      }
+    } catch (e) {
+    }
+  },
+  CLEAN_DICT: (state) => {
+    state.dict = new Array()
+  }
+}
+
+const actions = {
+  // 璁剧疆瀛楀吀
+  setDict({ commit }, data) {
+    commit('SET_DICT', data)
+  },
+  // 鍒犻櫎瀛楀吀
+  removeDict({ commit }, key) {
+    commit('REMOVE_DICT', key)
+  },
+  // 娓呯┖瀛楀吀
+  cleanDict({ commit }) {
+    commit('CLEAN_DICT')
+  }
+}
+
+export default {
+  namespaced: true,
+  state,
+  mutations,
+  actions
+}
+
diff --git a/jcdm-ui/src/store/modules/permission.js b/jcdm-ui/src/store/modules/permission.js
new file mode 100644
index 0000000..b3c216a
--- /dev/null
+++ b/jcdm-ui/src/store/modules/permission.js
@@ -0,0 +1,137 @@
+import auth from '@/plugins/auth'
+import router, { constantRoutes, dynamicRoutes } from '@/router'
+import { getRouters } from '@/api/menu'
+import Layout from '@/layout/index'
+import ParentView from '@/components/ParentView'
+import InnerLink from '@/layout/components/InnerLink'
+
+const permission = {
+  state: {
+    routes: [],
+    addRoutes: [],
+    defaultRoutes: [],
+    topbarRouters: [],
+    sidebarRouters: []
+  },
+  mutations: {
+    SET_ROUTES: (state, routes) => {
+      state.addRoutes = routes
+      state.routes = constantRoutes.concat(routes)
+    },
+    SET_DEFAULT_ROUTES: (state, routes) => {
+      state.defaultRoutes = constantRoutes.concat(routes)
+    },
+    SET_TOPBAR_ROUTES: (state, routes) => {
+      state.topbarRouters = routes
+    },
+    SET_SIDEBAR_ROUTERS: (state, routes) => {
+      state.sidebarRouters = routes
+    },
+  },
+  actions: {
+    // 鐢熸垚璺敱
+    GenerateRoutes({ commit }) {
+      return new Promise(resolve => {
+        // 鍚戝悗绔姹傝矾鐢辨暟鎹�
+        getRouters().then(res => {
+          const sdata = JSON.parse(JSON.stringify(res.data))
+          const rdata = JSON.parse(JSON.stringify(res.data))
+          const sidebarRoutes = filterAsyncRouter(sdata)
+          const rewriteRoutes = filterAsyncRouter(rdata, false, true)
+          const asyncRoutes = filterDynamicRoutes(dynamicRoutes);
+          rewriteRoutes.push({ path: '*', redirect: '/404', hidden: true })
+          router.addRoutes(asyncRoutes);
+          commit('SET_ROUTES', rewriteRoutes)
+          commit('SET_SIDEBAR_ROUTERS', constantRoutes.concat(sidebarRoutes))
+          commit('SET_DEFAULT_ROUTES', sidebarRoutes)
+          commit('SET_TOPBAR_ROUTES', sidebarRoutes)
+          resolve(rewriteRoutes)
+        })
+      })
+    }
+  }
+}
+
+// 閬嶅巻鍚庡彴浼犳潵鐨勮矾鐢卞瓧绗︿覆锛岃浆鎹负缁勪欢瀵硅薄
+function filterAsyncRouter(asyncRouterMap, lastRouter = false, type = false) {
+  return asyncRouterMap.filter(route => {
+    if (type && route.children) {
+      route.children = filterChildren(route.children)
+    }
+    if (route.component) {
+      // Layout ParentView 缁勪欢鐗规畩澶勭悊
+      if (route.component === 'Layout') {
+        route.component = Layout
+      } else if (route.component === 'ParentView') {
+        route.component = ParentView
+      } else if (route.component === 'InnerLink') {
+        route.component = InnerLink
+      } else {
+        route.component = loadView(route.component)
+      }
+    }
+    if (route.children != null && route.children && route.children.length) {
+      route.children = filterAsyncRouter(route.children, route, type)
+    } else {
+      delete route['children']
+      delete route['redirect']
+    }
+    return true
+  })
+}
+
+function filterChildren(childrenMap, lastRouter = false) {
+  var children = []
+  childrenMap.forEach((el, index) => {
+    if (el.children && el.children.length) {
+      if (el.component === 'ParentView' && !lastRouter) {
+        el.children.forEach(c => {
+          c.path = el.path + '/' + c.path
+          if (c.children && c.children.length) {
+            children = children.concat(filterChildren(c.children, c))
+            return
+          }
+          children.push(c)
+        })
+        return
+      }
+    }
+    if (lastRouter) {
+      el.path = lastRouter.path + '/' + el.path
+      if (el.children && el.children.length) {
+        children = children.concat(filterChildren(el.children, el))
+        return
+      }
+    }
+    children = children.concat(el)
+  })
+  return children
+}
+
+// 鍔ㄦ�佽矾鐢遍亶鍘嗭紝楠岃瘉鏄惁鍏峰鏉冮檺
+export function filterDynamicRoutes(routes) {
+  const res = []
+  routes.forEach(route => {
+    if (route.permissions) {
+      if (auth.hasPermiOr(route.permissions)) {
+        res.push(route)
+      }
+    } else if (route.roles) {
+      if (auth.hasRoleOr(route.roles)) {
+        res.push(route)
+      }
+    }
+  })
+  return res
+}
+
+export const loadView = (view) => {
+  if (process.env.NODE_ENV === 'development') {
+    return (resolve) => require([`@/views/${view}`], resolve)
+  } else {
+    // 浣跨敤 import 瀹炵幇鐢熶骇鐜鐨勮矾鐢辨噿鍔犺浇
+    return () => import(`@/views/${view}`)
+  }
+}
+
+export default permission
diff --git a/jcdm-ui/src/store/modules/settings.js b/jcdm-ui/src/store/modules/settings.js
new file mode 100644
index 0000000..2455a1e
--- /dev/null
+++ b/jcdm-ui/src/store/modules/settings.js
@@ -0,0 +1,42 @@
+import defaultSettings from '@/settings'
+
+const { sideTheme, showSettings, topNav, tagsView, fixedHeader, sidebarLogo, dynamicTitle } = defaultSettings
+
+const storageSetting = JSON.parse(localStorage.getItem('layout-setting')) || ''
+const state = {
+  title: '',
+  theme: storageSetting.theme || '#409EFF',
+  sideTheme: storageSetting.sideTheme || sideTheme,
+  showSettings: showSettings,
+  topNav: storageSetting.topNav === undefined ? topNav : storageSetting.topNav,
+  tagsView: storageSetting.tagsView === undefined ? tagsView : storageSetting.tagsView,
+  fixedHeader: storageSetting.fixedHeader === undefined ? fixedHeader : storageSetting.fixedHeader,
+  sidebarLogo: storageSetting.sidebarLogo === undefined ? sidebarLogo : storageSetting.sidebarLogo,
+  dynamicTitle: storageSetting.dynamicTitle === undefined ? dynamicTitle : storageSetting.dynamicTitle
+}
+const mutations = {
+  CHANGE_SETTING: (state, { key, value }) => {
+    if (state.hasOwnProperty(key)) {
+      state[key] = value
+    }
+  }
+}
+
+const actions = {
+  // 淇敼甯冨眬璁剧疆
+  changeSetting({ commit }, data) {
+    commit('CHANGE_SETTING', data)
+  },
+  // 璁剧疆缃戦〉鏍囬
+  setTitle({ commit }, title) {
+    state.title = title
+  }
+}
+
+export default {
+  namespaced: true,
+  state,
+  mutations,
+  actions
+}
+
diff --git a/jcdm-ui/src/store/modules/tagsView.js b/jcdm-ui/src/store/modules/tagsView.js
new file mode 100644
index 0000000..5fc011c
--- /dev/null
+++ b/jcdm-ui/src/store/modules/tagsView.js
@@ -0,0 +1,228 @@
+const state = {
+  visitedViews: [],
+  cachedViews: [],
+  iframeViews: []
+}
+
+const mutations = {
+  ADD_IFRAME_VIEW: (state, view) => {
+    if (state.iframeViews.some(v => v.path === view.path)) return
+    state.iframeViews.push(
+      Object.assign({}, view, {
+        title: view.meta.title || 'no-name'
+      })
+    )
+  },
+  ADD_VISITED_VIEW: (state, view) => {
+    if (state.visitedViews.some(v => v.path === view.path)) return
+    state.visitedViews.push(
+      Object.assign({}, view, {
+        title: view.meta.title || 'no-name'
+      })
+    )
+  },
+  ADD_CACHED_VIEW: (state, view) => {
+    if (state.cachedViews.includes(view.name)) return
+    if (view.meta && !view.meta.noCache) {
+      state.cachedViews.push(view.name)
+    }
+  },
+  DEL_VISITED_VIEW: (state, view) => {
+    for (const [i, v] of state.visitedViews.entries()) {
+      if (v.path === view.path) {
+        state.visitedViews.splice(i, 1)
+        break
+      }
+    }
+    state.iframeViews = state.iframeViews.filter(item => item.path !== view.path)
+  },
+  DEL_IFRAME_VIEW: (state, view) => {
+    state.iframeViews = state.iframeViews.filter(item => item.path !== view.path)
+  },
+  DEL_CACHED_VIEW: (state, view) => {
+    const index = state.cachedViews.indexOf(view.name)
+    index > -1 && state.cachedViews.splice(index, 1)
+  },
+
+  DEL_OTHERS_VISITED_VIEWS: (state, view) => {
+    state.visitedViews = state.visitedViews.filter(v => {
+      return v.meta.affix || v.path === view.path
+    })
+    state.iframeViews = state.iframeViews.filter(item => item.path === view.path)
+  },
+  DEL_OTHERS_CACHED_VIEWS: (state, view) => {
+    const index = state.cachedViews.indexOf(view.name)
+    if (index > -1) {
+      state.cachedViews = state.cachedViews.slice(index, index + 1)
+    } else {
+      state.cachedViews = []
+    }
+  },
+  DEL_ALL_VISITED_VIEWS: state => {
+    // keep affix tags
+    const affixTags = state.visitedViews.filter(tag => tag.meta.affix)
+    state.visitedViews = affixTags
+    state.iframeViews = []
+  },
+  DEL_ALL_CACHED_VIEWS: state => {
+    state.cachedViews = []
+  },
+  UPDATE_VISITED_VIEW: (state, view) => {
+    for (let v of state.visitedViews) {
+      if (v.path === view.path) {
+        v = Object.assign(v, view)
+        break
+      }
+    }
+  },
+  DEL_RIGHT_VIEWS: (state, view) => {
+    const index = state.visitedViews.findIndex(v => v.path === view.path)
+    if (index === -1) {
+      return
+    }
+    state.visitedViews = state.visitedViews.filter((item, idx) => {
+      if (idx <= index || (item.meta && item.meta.affix)) {
+        return true
+      }
+      const i = state.cachedViews.indexOf(item.name)
+      if (i > -1) {
+        state.cachedViews.splice(i, 1)
+      }
+      if(item.meta.link) {
+        const fi = state.iframeViews.findIndex(v => v.path === item.path)
+        state.iframeViews.splice(fi, 1)
+      }
+      return false
+    })
+  },
+  DEL_LEFT_VIEWS: (state, view) => {
+    const index = state.visitedViews.findIndex(v => v.path === view.path)
+    if (index === -1) {
+      return
+    }
+    state.visitedViews = state.visitedViews.filter((item, idx) => {
+      if (idx >= index || (item.meta && item.meta.affix)) {
+        return true
+      }
+      const i = state.cachedViews.indexOf(item.name)
+      if (i > -1) {
+        state.cachedViews.splice(i, 1)
+      }
+      if(item.meta.link) {
+        const fi = state.iframeViews.findIndex(v => v.path === item.path)
+        state.iframeViews.splice(fi, 1)
+      }
+      return false
+    })
+  }
+}
+
+const actions = {
+  addView({ dispatch }, view) {
+    dispatch('addVisitedView', view)
+    dispatch('addCachedView', view)
+  },
+  addIframeView({ commit }, view) {
+    commit('ADD_IFRAME_VIEW', view)
+  },
+  addVisitedView({ commit }, view) {
+    commit('ADD_VISITED_VIEW', view)
+  },
+  addCachedView({ commit }, view) {
+    commit('ADD_CACHED_VIEW', view)
+  },
+  delView({ dispatch, state }, view) {
+    return new Promise(resolve => {
+      dispatch('delVisitedView', view)
+      dispatch('delCachedView', view)
+      resolve({
+        visitedViews: [...state.visitedViews],
+        cachedViews: [...state.cachedViews]
+      })
+    })
+  },
+  delVisitedView({ commit, state }, view) {
+    return new Promise(resolve => {
+      commit('DEL_VISITED_VIEW', view)
+      resolve([...state.visitedViews])
+    })
+  },
+  delIframeView({ commit, state }, view) {
+    return new Promise(resolve => {
+      commit('DEL_IFRAME_VIEW', view)
+      resolve([...state.iframeViews])
+    })
+  },
+  delCachedView({ commit, state }, view) {
+    return new Promise(resolve => {
+      commit('DEL_CACHED_VIEW', view)
+      resolve([...state.cachedViews])
+    })
+  },
+  delOthersViews({ dispatch, state }, view) {
+    return new Promise(resolve => {
+      dispatch('delOthersVisitedViews', view)
+      dispatch('delOthersCachedViews', view)
+      resolve({
+        visitedViews: [...state.visitedViews],
+        cachedViews: [...state.cachedViews]
+      })
+    })
+  },
+  delOthersVisitedViews({ commit, state }, view) {
+    return new Promise(resolve => {
+      commit('DEL_OTHERS_VISITED_VIEWS', view)
+      resolve([...state.visitedViews])
+    })
+  },
+  delOthersCachedViews({ commit, state }, view) {
+    return new Promise(resolve => {
+      commit('DEL_OTHERS_CACHED_VIEWS', view)
+      resolve([...state.cachedViews])
+    })
+  },
+  delAllViews({ dispatch, state }, view) {
+    return new Promise(resolve => {
+      dispatch('delAllVisitedViews', view)
+      dispatch('delAllCachedViews', view)
+      resolve({
+        visitedViews: [...state.visitedViews],
+        cachedViews: [...state.cachedViews]
+      })
+    })
+  },
+  delAllVisitedViews({ commit, state }) {
+    return new Promise(resolve => {
+      commit('DEL_ALL_VISITED_VIEWS')
+      resolve([...state.visitedViews])
+    })
+  },
+  delAllCachedViews({ commit, state }) {
+    return new Promise(resolve => {
+      commit('DEL_ALL_CACHED_VIEWS')
+      resolve([...state.cachedViews])
+    })
+  },
+  updateVisitedView({ commit }, view) {
+    commit('UPDATE_VISITED_VIEW', view)
+  },
+  delRightTags({ commit }, view) {
+    return new Promise(resolve => {
+      commit('DEL_RIGHT_VIEWS', view)
+      resolve([...state.visitedViews])
+    })
+  },
+  delLeftTags({ commit }, view) {
+    return new Promise(resolve => {
+      commit('DEL_LEFT_VIEWS', view)
+      resolve([...state.visitedViews])
+    })
+  },
+}
+
+export default {
+  namespaced: true,
+  state,
+  mutations,
+  actions
+}
diff --git a/jcdm-ui/src/store/modules/user.js b/jcdm-ui/src/store/modules/user.js
new file mode 100644
index 0000000..cdbab1e
--- /dev/null
+++ b/jcdm-ui/src/store/modules/user.js
@@ -0,0 +1,101 @@
+import { login, logout, getInfo } from '@/api/login'
+import { getToken, setToken, removeToken } from '@/utils/auth'
+
+const user = {
+  state: {
+    token: getToken(),
+    id: '',
+    name: '',
+    avatar: '',
+    roles: [],
+    permissions: []
+  },
+
+  mutations: {
+    SET_TOKEN: (state, token) => {
+      state.token = token
+    },
+    SET_ID: (state, id) => {
+      state.id = id
+    },
+    SET_NAME: (state, name) => {
+      state.name = name
+    },
+    SET_AVATAR: (state, avatar) => {
+      state.avatar = avatar
+    },
+    SET_ROLES: (state, roles) => {
+      state.roles = roles
+    },
+    SET_PERMISSIONS: (state, permissions) => {
+      state.permissions = permissions
+    }
+  },
+
+  actions: {
+    // 鐧诲綍
+    Login({ commit }, userInfo) {
+      const username = userInfo.username.trim()
+      const password = userInfo.password
+      const code = userInfo.code
+      const uuid = userInfo.uuid
+      return new Promise((resolve, reject) => {
+        login(username, password, code, uuid).then(res => {
+          setToken(res.token)
+          commit('SET_TOKEN', res.token)
+          resolve()
+        }).catch(error => {
+          reject(error)
+        })
+      })
+    },
+
+    // 鑾峰彇鐢ㄦ埛淇℃伅
+    GetInfo({ commit, state }) {
+      return new Promise((resolve, reject) => {
+        getInfo().then(res => {
+          const user = res.user
+          const avatar = (user.avatar == "" || user.avatar == null) ? require("@/assets/images/profile.jpg") : process.env.VUE_APP_BASE_API + user.avatar;
+          if (res.roles && res.roles.length > 0) { // 楠岃瘉杩斿洖鐨剅oles鏄惁鏄竴涓潪绌烘暟缁�
+            commit('SET_ROLES', res.roles)
+            commit('SET_PERMISSIONS', res.permissions)
+          } else {
+            commit('SET_ROLES', ['ROLE_DEFAULT'])
+          }
+          commit('SET_ID', user.userId)
+          commit('SET_NAME', user.userName)
+          commit('SET_AVATAR', avatar)
+          resolve(res)
+        }).catch(error => {
+          reject(error)
+        })
+      })
+    },
+
+    // 閫�鍑虹郴缁�
+    LogOut({ commit, state }) {
+      return new Promise((resolve, reject) => {
+        logout(state.token).then(() => {
+          commit('SET_TOKEN', '')
+          commit('SET_ROLES', [])
+          commit('SET_PERMISSIONS', [])
+          removeToken()
+          resolve()
+        }).catch(error => {
+          reject(error)
+        })
+      })
+    },
+
+    // 鍓嶇 鐧诲嚭
+    FedLogOut({ commit }) {
+      return new Promise(resolve => {
+        commit('SET_TOKEN', '')
+        removeToken()
+        resolve()
+      })
+    }
+  }
+}
+
+export default user
diff --git a/jcdm-ui/src/utils/auth.js b/jcdm-ui/src/utils/auth.js
new file mode 100644
index 0000000..08a43d6
--- /dev/null
+++ b/jcdm-ui/src/utils/auth.js
@@ -0,0 +1,15 @@
+import Cookies from 'js-cookie'
+
+const TokenKey = 'Admin-Token'
+
+export function getToken() {
+  return Cookies.get(TokenKey)
+}
+
+export function setToken(token) {
+  return Cookies.set(TokenKey, token)
+}
+
+export function removeToken() {
+  return Cookies.remove(TokenKey)
+}
diff --git a/jcdm-ui/src/utils/dict/Dict.js b/jcdm-ui/src/utils/dict/Dict.js
new file mode 100644
index 0000000..104bd6e
--- /dev/null
+++ b/jcdm-ui/src/utils/dict/Dict.js
@@ -0,0 +1,82 @@
+import Vue from 'vue'
+import { mergeRecursive } from "@/utils/ruoyi";
+import DictMeta from './DictMeta'
+import DictData from './DictData'
+
+const DEFAULT_DICT_OPTIONS = {
+  types: [],
+}
+
+/**
+ * @classdesc 瀛楀吀
+ * @property {Object} label 鏍囩瀵硅薄锛屽唴閮ㄥ睘鎬у悕涓哄瓧鍏哥被鍨嬪悕绉�
+ * @property {Object} dict 瀛楁鏁扮粍锛屽唴閮ㄥ睘鎬у悕涓哄瓧鍏哥被鍨嬪悕绉�
+ * @property {Array.<DictMeta>} _dictMetas 瀛楀吀鍏冩暟鎹暟缁�
+ */
+export default class Dict {
+  constructor() {
+    this.owner = null
+    this.label = {}
+    this.type = {}
+  }
+
+  init(options) {
+    if (options instanceof Array) {
+      options = { types: options }
+    }
+    const opts = mergeRecursive(DEFAULT_DICT_OPTIONS, options)
+    if (opts.types === undefined) {
+      throw new Error('need dict types')
+    }
+    const ps = []
+    this._dictMetas = opts.types.map(t => DictMeta.parse(t))
+    this._dictMetas.forEach(dictMeta => {
+      const type = dictMeta.type
+      Vue.set(this.label, type, {})
+      Vue.set(this.type, type, [])
+      if (dictMeta.lazy) {
+        return
+      }
+      ps.push(loadDict(this, dictMeta))
+    })
+    return Promise.all(ps)
+  }
+
+  /**
+   * 閲嶆柊鍔犺浇瀛楀吀
+   * @param {String} type 瀛楀吀绫诲瀷
+   */
+  reloadDict(type) {
+    const dictMeta = this._dictMetas.find(e => e.type === type)
+    if (dictMeta === undefined) {
+      return Promise.reject(`the dict meta of ${type} was not found`)
+    }
+    return loadDict(this, dictMeta)
+  }
+}
+
+/**
+ * 鍔犺浇瀛楀吀
+ * @param {Dict} dict 瀛楀吀
+ * @param {DictMeta} dictMeta 瀛楀吀鍏冩暟鎹�
+ * @returns {Promise}
+ */
+function loadDict(dict, dictMeta) {
+  return dictMeta.request(dictMeta)
+    .then(response => {
+      const type = dictMeta.type
+      let dicts = dictMeta.responseConverter(response, dictMeta)
+      if (!(dicts instanceof Array)) {
+        console.error('the return of responseConverter must be Array.<DictData>')
+        dicts = []
+      } else if (dicts.filter(d => d instanceof DictData).length !== dicts.length) {
+        console.error('the type of elements in dicts must be DictData')
+        dicts = []
+      }
+      dict.type[type].splice(0, Number.MAX_SAFE_INTEGER, ...dicts)
+      dicts.forEach(d => {
+        Vue.set(dict.label[type], d.value, d.label)
+      })
+      return dicts
+    })
+}
diff --git a/jcdm-ui/src/utils/dict/DictConverter.js b/jcdm-ui/src/utils/dict/DictConverter.js
new file mode 100644
index 0000000..0cf5df8
--- /dev/null
+++ b/jcdm-ui/src/utils/dict/DictConverter.js
@@ -0,0 +1,17 @@
+import DictOptions from './DictOptions'
+import DictData from './DictData'
+
+export default function(dict, dictMeta) {
+  const label = determineDictField(dict, dictMeta.labelField, ...DictOptions.DEFAULT_LABEL_FIELDS)
+  const value = determineDictField(dict, dictMeta.valueField, ...DictOptions.DEFAULT_VALUE_FIELDS)
+  return new DictData(dict[label], dict[value], dict)
+}
+
+/**
+ * 纭畾瀛楀吀瀛楁
+ * @param {DictData} dict
+ * @param  {...String} fields
+ */
+function determineDictField(dict, ...fields) {
+  return fields.find(f => Object.prototype.hasOwnProperty.call(dict, f))
+}
diff --git a/jcdm-ui/src/utils/dict/DictData.js b/jcdm-ui/src/utils/dict/DictData.js
new file mode 100644
index 0000000..afc763e
--- /dev/null
+++ b/jcdm-ui/src/utils/dict/DictData.js
@@ -0,0 +1,13 @@
+/**
+ * @classdesc 瀛楀吀鏁版嵁
+ * @property {String} label 鏍囩
+ * @property {*} value 鏍囩
+ * @property {Object} raw 鍘熷鏁版嵁
+ */
+export default class DictData {
+  constructor(label, value, raw) {
+    this.label = label
+    this.value = value
+    this.raw = raw
+  }
+}
diff --git a/jcdm-ui/src/utils/dict/DictMeta.js b/jcdm-ui/src/utils/dict/DictMeta.js
new file mode 100644
index 0000000..9779daa
--- /dev/null
+++ b/jcdm-ui/src/utils/dict/DictMeta.js
@@ -0,0 +1,38 @@
+import { mergeRecursive } from "@/utils/ruoyi";
+import DictOptions from './DictOptions'
+
+/**
+ * @classdesc 瀛楀吀鍏冩暟鎹�
+ * @property {String} type 绫诲瀷
+ * @property {Function} request 璇锋眰
+ * @property {String} label 鏍囩瀛楁
+ * @property {String} value 鍊煎瓧娈�
+ */
+export default class DictMeta {
+  constructor(options) {
+    this.type = options.type
+    this.request = options.request
+    this.responseConverter = options.responseConverter
+    this.labelField = options.labelField
+    this.valueField = options.valueField
+    this.lazy = options.lazy === true
+  }
+}
+
+
+/**
+ * 瑙f瀽瀛楀吀鍏冩暟鎹�
+ * @param {Object} options
+ * @returns {DictMeta}
+ */
+DictMeta.parse= function(options) {
+  let opts = null
+  if (typeof options === 'string') {
+    opts = DictOptions.metas[options] || {}
+    opts.type = options
+  } else if (typeof options === 'object') {
+    opts = options
+  }
+  opts = mergeRecursive(DictOptions.metas['*'], opts)
+  return new DictMeta(opts)
+}
diff --git a/jcdm-ui/src/utils/dict/DictOptions.js b/jcdm-ui/src/utils/dict/DictOptions.js
new file mode 100644
index 0000000..338a94e
--- /dev/null
+++ b/jcdm-ui/src/utils/dict/DictOptions.js
@@ -0,0 +1,51 @@
+import { mergeRecursive } from "@/utils/ruoyi";
+import dictConverter from './DictConverter'
+
+export const options = {
+  metas: {
+    '*': {
+      /**
+       * 瀛楀吀璇锋眰锛屾柟娉曠鍚嶄负function(dictMeta: DictMeta): Promise
+       */
+      request: (dictMeta) => {
+        console.log(`load dict ${dictMeta.type}`)
+        return Promise.resolve([])
+      },
+      /**
+       * 瀛楀吀鍝嶅簲鏁版嵁杞崲鍣紝鏂规硶绛惧悕涓篺unction(response: Object, dictMeta: DictMeta): DictData
+       */
+      responseConverter,
+      labelField: 'label',
+      valueField: 'value',
+    },
+  },
+  /**
+   * 榛樿鏍囩瀛楁
+   */
+  DEFAULT_LABEL_FIELDS: ['label', 'name', 'title'],
+  /**
+   * 榛樿鍊煎瓧娈�
+   */
+  DEFAULT_VALUE_FIELDS: ['value', 'id', 'uid', 'key'],
+}
+
+/**
+ * 鏄犲皠瀛楀吀
+ * @param {Object} response 瀛楀吀鏁版嵁
+ * @param {DictMeta} dictMeta 瀛楀吀鍏冩暟鎹�
+ * @returns {DictData}
+ */
+function responseConverter(response, dictMeta) {
+  const dicts = response.content instanceof Array ? response.content : response
+  if (dicts === undefined) {
+    console.warn(`no dict data of "${dictMeta.type}" found in the response`)
+    return []
+  }
+  return dicts.map(d => dictConverter(d, dictMeta))
+}
+
+export function mergeOptions(src) {
+  mergeRecursive(options, src)
+}
+
+export default options
diff --git a/jcdm-ui/src/utils/dict/index.js b/jcdm-ui/src/utils/dict/index.js
new file mode 100644
index 0000000..215eb9e
--- /dev/null
+++ b/jcdm-ui/src/utils/dict/index.js
@@ -0,0 +1,33 @@
+import Dict from './Dict'
+import { mergeOptions } from './DictOptions'
+
+export default function(Vue, options) {
+  mergeOptions(options)
+  Vue.mixin({
+    data() {
+      if (this.$options === undefined || this.$options.dicts === undefined || this.$options.dicts === null) {
+        return {}
+      }
+      const dict = new Dict()
+      dict.owner = this
+      return {
+        dict
+      }
+    },
+    created() {
+      if (!(this.dict instanceof Dict)) {
+        return
+      }
+      options.onCreated && options.onCreated(this.dict)
+      this.dict.init(this.$options.dicts).then(() => {
+        options.onReady && options.onReady(this.dict)
+        this.$nextTick(() => {
+          this.$emit('dictReady', this.dict)
+          if (this.$options.methods && this.$options.methods.onDictReady instanceof Function) {
+            this.$options.methods.onDictReady.call(this, this.dict)
+          }
+        })
+      })
+    },
+  })
+}
diff --git a/jcdm-ui/src/utils/errorCode.js b/jcdm-ui/src/utils/errorCode.js
new file mode 100644
index 0000000..d2111ee
--- /dev/null
+++ b/jcdm-ui/src/utils/errorCode.js
@@ -0,0 +1,6 @@
+export default {
+  '401': '璁よ瘉澶辫触锛屾棤娉曡闂郴缁熻祫婧�',
+  '403': '褰撳墠鎿嶄綔娌℃湁鏉冮檺',
+  '404': '璁块棶璧勬簮涓嶅瓨鍦�',
+  'default': '绯荤粺鏈煡閿欒锛岃鍙嶉缁欑鐞嗗憳'
+}
diff --git a/jcdm-ui/src/utils/generator/config.js b/jcdm-ui/src/utils/generator/config.js
new file mode 100644
index 0000000..7abf227
--- /dev/null
+++ b/jcdm-ui/src/utils/generator/config.js
@@ -0,0 +1,438 @@
+export const formConf = {
+  formRef: 'elForm',
+  formModel: 'formData',
+  size: 'medium',
+  labelPosition: 'right',
+  labelWidth: 100,
+  formRules: 'rules',
+  gutter: 15,
+  disabled: false,
+  span: 24,
+  formBtns: true
+}
+
+export const inputComponents = [
+  {
+    label: '鍗曡鏂囨湰',
+    tag: 'el-input',
+    tagIcon: 'input',
+    placeholder: '璇疯緭鍏�',
+    defaultValue: undefined,
+    span: 24,
+    labelWidth: null,
+    style: { width: '100%' },
+    clearable: true,
+    prepend: '',
+    append: '',
+    'prefix-icon': '',
+    'suffix-icon': '',
+    maxlength: null,
+    'show-word-limit': false,
+    readonly: false,
+    disabled: false,
+    required: true,
+    regList: [],
+    changeTag: true,
+    document: 'https://element.eleme.cn/#/zh-CN/component/input'
+  },
+  {
+    label: '澶氳鏂囨湰',
+    tag: 'el-input',
+    tagIcon: 'textarea',
+    type: 'textarea',
+    placeholder: '璇疯緭鍏�',
+    defaultValue: undefined,
+    span: 24,
+    labelWidth: null,
+    autosize: {
+      minRows: 4,
+      maxRows: 4
+    },
+    style: { width: '100%' },
+    maxlength: null,
+    'show-word-limit': false,
+    readonly: false,
+    disabled: false,
+    required: true,
+    regList: [],
+    changeTag: true,
+    document: 'https://element.eleme.cn/#/zh-CN/component/input'
+  },
+  {
+    label: '瀵嗙爜',
+    tag: 'el-input',
+    tagIcon: 'password',
+    placeholder: '璇疯緭鍏�',
+    defaultValue: undefined,
+    span: 24,
+    'show-password': true,
+    labelWidth: null,
+    style: { width: '100%' },
+    clearable: true,
+    prepend: '',
+    append: '',
+    'prefix-icon': '',
+    'suffix-icon': '',
+    maxlength: null,
+    'show-word-limit': false,
+    readonly: false,
+    disabled: false,
+    required: true,
+    regList: [],
+    changeTag: true,
+    document: 'https://element.eleme.cn/#/zh-CN/component/input'
+  },
+  {
+    label: '璁℃暟鍣�',
+    tag: 'el-input-number',
+    tagIcon: 'number',
+    placeholder: '',
+    defaultValue: undefined,
+    span: 24,
+    labelWidth: null,
+    min: undefined,
+    max: undefined,
+    step: undefined,
+    'step-strictly': false,
+    precision: undefined,
+    'controls-position': '',
+    disabled: false,
+    required: true,
+    regList: [],
+    changeTag: true,
+    document: 'https://element.eleme.cn/#/zh-CN/component/input-number'
+  }
+]
+
+export const selectComponents = [
+  {
+    label: '涓嬫媺閫夋嫨',
+    tag: 'el-select',
+    tagIcon: 'select',
+    placeholder: '璇烽�夋嫨',
+    defaultValue: undefined,
+    span: 24,
+    labelWidth: null,
+    style: { width: '100%' },
+    clearable: true,
+    disabled: false,
+    required: true,
+    filterable: false,
+    multiple: false,
+    options: [{
+      label: '閫夐」涓�',
+      value: 1
+    }, {
+      label: '閫夐」浜�',
+      value: 2
+    }],
+    regList: [],
+    changeTag: true,
+    document: 'https://element.eleme.cn/#/zh-CN/component/select'
+  },
+  {
+    label: '绾ц仈閫夋嫨',
+    tag: 'el-cascader',
+    tagIcon: 'cascader',
+    placeholder: '璇烽�夋嫨',
+    defaultValue: [],
+    span: 24,
+    labelWidth: null,
+    style: { width: '100%' },
+    props: {
+      props: {
+        multiple: false
+      }
+    },
+    'show-all-levels': true,
+    disabled: false,
+    clearable: true,
+    filterable: false,
+    required: true,
+    options: [{
+      id: 1,
+      value: 1,
+      label: '閫夐」1',
+      children: [{
+        id: 2,
+        value: 2,
+        label: '閫夐」1-1'
+      }]
+    }],
+    dataType: 'dynamic',
+    labelKey: 'label',
+    valueKey: 'value',
+    childrenKey: 'children',
+    separator: '/',
+    regList: [],
+    changeTag: true,
+    document: 'https://element.eleme.cn/#/zh-CN/component/cascader'
+  },
+  {
+    label: '鍗曢�夋缁�',
+    tag: 'el-radio-group',
+    tagIcon: 'radio',
+    defaultValue: undefined,
+    span: 24,
+    labelWidth: null,
+    style: {},
+    optionType: 'default',
+    border: false,
+    size: 'medium',
+    disabled: false,
+    required: true,
+    options: [{
+      label: '閫夐」涓�',
+      value: 1
+    }, {
+      label: '閫夐」浜�',
+      value: 2
+    }],
+    regList: [],
+    changeTag: true,
+    document: 'https://element.eleme.cn/#/zh-CN/component/radio'
+  },
+  {
+    label: '澶氶�夋缁�',
+    tag: 'el-checkbox-group',
+    tagIcon: 'checkbox',
+    defaultValue: [],
+    span: 24,
+    labelWidth: null,
+    style: {},
+    optionType: 'default',
+    border: false,
+    size: 'medium',
+    disabled: false,
+    required: true,
+    options: [{
+      label: '閫夐」涓�',
+      value: 1
+    }, {
+      label: '閫夐」浜�',
+      value: 2
+    }],
+    regList: [],
+    changeTag: true,
+    document: 'https://element.eleme.cn/#/zh-CN/component/checkbox'
+  },
+  {
+    label: '寮�鍏�',
+    tag: 'el-switch',
+    tagIcon: 'switch',
+    defaultValue: false,
+    span: 24,
+    labelWidth: null,
+    style: {},
+    disabled: false,
+    required: true,
+    'active-text': '',
+    'inactive-text': '',
+    'active-color': null,
+    'inactive-color': null,
+    'active-value': true,
+    'inactive-value': false,
+    regList: [],
+    changeTag: true,
+    document: 'https://element.eleme.cn/#/zh-CN/component/switch'
+  },
+  {
+    label: '婊戝潡',
+    tag: 'el-slider',
+    tagIcon: 'slider',
+    defaultValue: null,
+    span: 24,
+    labelWidth: null,
+    disabled: false,
+    required: true,
+    min: 0,
+    max: 100,
+    step: 1,
+    'show-stops': false,
+    range: false,
+    regList: [],
+    changeTag: true,
+    document: 'https://element.eleme.cn/#/zh-CN/component/slider'
+  },
+  {
+    label: '鏃堕棿閫夋嫨',
+    tag: 'el-time-picker',
+    tagIcon: 'time',
+    placeholder: '璇烽�夋嫨',
+    defaultValue: null,
+    span: 24,
+    labelWidth: null,
+    style: { width: '100%' },
+    disabled: false,
+    clearable: true,
+    required: true,
+    'picker-options': {
+      selectableRange: '00:00:00-23:59:59'
+    },
+    format: 'HH:mm:ss',
+    'value-format': 'HH:mm:ss',
+    regList: [],
+    changeTag: true,
+    document: 'https://element.eleme.cn/#/zh-CN/component/time-picker'
+  },
+  {
+    label: '鏃堕棿鑼冨洿',
+    tag: 'el-time-picker',
+    tagIcon: 'time-range',
+    defaultValue: null,
+    span: 24,
+    labelWidth: null,
+    style: { width: '100%' },
+    disabled: false,
+    clearable: true,
+    required: true,
+    'is-range': true,
+    'range-separator': '鑷�',
+    'start-placeholder': '寮�濮嬫椂闂�',
+    'end-placeholder': '缁撴潫鏃堕棿',
+    format: 'HH:mm:ss',
+    'value-format': 'HH:mm:ss',
+    regList: [],
+    changeTag: true,
+    document: 'https://element.eleme.cn/#/zh-CN/component/time-picker'
+  },
+  {
+    label: '鏃ユ湡閫夋嫨',
+    tag: 'el-date-picker',
+    tagIcon: 'date',
+    placeholder: '璇烽�夋嫨',
+    defaultValue: null,
+    type: 'date',
+    span: 24,
+    labelWidth: null,
+    style: { width: '100%' },
+    disabled: false,
+    clearable: true,
+    required: true,
+    format: 'yyyy-MM-dd',
+    'value-format': 'yyyy-MM-dd',
+    readonly: false,
+    regList: [],
+    changeTag: true,
+    document: 'https://element.eleme.cn/#/zh-CN/component/date-picker'
+  },
+  {
+    label: '鏃ユ湡鑼冨洿',
+    tag: 'el-date-picker',
+    tagIcon: 'date-range',
+    defaultValue: null,
+    span: 24,
+    labelWidth: null,
+    style: { width: '100%' },
+    type: 'daterange',
+    'range-separator': '鑷�',
+    'start-placeholder': '寮�濮嬫棩鏈�',
+    'end-placeholder': '缁撴潫鏃ユ湡',
+    disabled: false,
+    clearable: true,
+    required: true,
+    format: 'yyyy-MM-dd',
+    'value-format': 'yyyy-MM-dd',
+    readonly: false,
+    regList: [],
+    changeTag: true,
+    document: 'https://element.eleme.cn/#/zh-CN/component/date-picker'
+  },
+  {
+    label: '璇勫垎',
+    tag: 'el-rate',
+    tagIcon: 'rate',
+    defaultValue: 0,
+    span: 24,
+    labelWidth: null,
+    style: {},
+    max: 5,
+    'allow-half': false,
+    'show-text': false,
+    'show-score': false,
+    disabled: false,
+    required: true,
+    regList: [],
+    changeTag: true,
+    document: 'https://element.eleme.cn/#/zh-CN/component/rate'
+  },
+  {
+    label: '棰滆壊閫夋嫨',
+    tag: 'el-color-picker',
+    tagIcon: 'color',
+    defaultValue: null,
+    labelWidth: null,
+    'show-alpha': false,
+    'color-format': '',
+    disabled: false,
+    required: true,
+    size: 'medium',
+    regList: [],
+    changeTag: true,
+    document: 'https://element.eleme.cn/#/zh-CN/component/color-picker'
+  },
+  {
+    label: '涓婁紶',
+    tag: 'el-upload',
+    tagIcon: 'upload',
+    action: 'https://jsonplaceholder.typicode.com/posts/',
+    defaultValue: null,
+    labelWidth: null,
+    disabled: false,
+    required: true,
+    accept: '',
+    name: 'file',
+    'auto-upload': true,
+    showTip: false,
+    buttonText: '鐐瑰嚮涓婁紶',
+    fileSize: 2,
+    sizeUnit: 'MB',
+    'list-type': 'text',
+    multiple: false,
+    regList: [],
+    changeTag: true,
+    document: 'https://element.eleme.cn/#/zh-CN/component/upload'
+  }
+]
+
+export const layoutComponents = [
+  {
+    layout: 'rowFormItem',
+    tagIcon: 'row',
+    type: 'default',
+    justify: 'start',
+    align: 'top',
+    label: '琛屽鍣�',
+    layoutTree: true,
+    children: [],
+    document: 'https://element.eleme.cn/#/zh-CN/component/layout'
+  },
+  {
+    layout: 'colFormItem',
+    label: '鎸夐挳',
+    changeTag: true,
+    labelWidth: null,
+    tag: 'el-button',
+    tagIcon: 'button',
+    span: 24,
+    default: '涓昏鎸夐挳',
+    type: 'primary',
+    icon: 'el-icon-search',
+    size: 'medium',
+    disabled: false,
+    document: 'https://element.eleme.cn/#/zh-CN/component/button'
+  }
+]
+
+// 缁勪欢rule鐨勮Е鍙戞柟寮忥紝鏃犺Е鍙戞柟寮忕殑缁勪欢涓嶇敓鎴恟ule
+export const trigger = {
+  'el-input': 'blur',
+  'el-input-number': 'blur',
+  'el-select': 'change',
+  'el-radio-group': 'change',
+  'el-checkbox-group': 'change',
+  'el-cascader': 'change',
+  'el-time-picker': 'change',
+  'el-date-picker': 'change',
+  'el-rate': 'change'
+}
diff --git a/jcdm-ui/src/utils/generator/css.js b/jcdm-ui/src/utils/generator/css.js
new file mode 100644
index 0000000..c1c62e6
--- /dev/null
+++ b/jcdm-ui/src/utils/generator/css.js
@@ -0,0 +1,18 @@
+const styles = {
+  'el-rate': '.el-rate{display: inline-block; vertical-align: text-top;}',
+  'el-upload': '.el-upload__tip{line-height: 1.2;}'
+}
+
+function addCss(cssList, el) {
+  const css = styles[el.tag]
+  css && cssList.indexOf(css) === -1 && cssList.push(css)
+  if (el.children) {
+    el.children.forEach(el2 => addCss(cssList, el2))
+  }
+}
+
+export function makeUpCss(conf) {
+  const cssList = []
+  conf.fields.forEach(el => addCss(cssList, el))
+  return cssList.join('\n')
+}
diff --git a/jcdm-ui/src/utils/generator/drawingDefault.js b/jcdm-ui/src/utils/generator/drawingDefault.js
new file mode 100644
index 0000000..09f133c
--- /dev/null
+++ b/jcdm-ui/src/utils/generator/drawingDefault.js
@@ -0,0 +1,29 @@
+export default [
+  {
+    layout: 'colFormItem',
+    tagIcon: 'input',
+    label: '鎵嬫満鍙�',
+    vModel: 'mobile',
+    formId: 6,
+    tag: 'el-input',
+    placeholder: '璇疯緭鍏ユ墜鏈哄彿',
+    defaultValue: '',
+    span: 24,
+    style: { width: '100%' },
+    clearable: true,
+    prepend: '',
+    append: '',
+    'prefix-icon': 'el-icon-mobile',
+    'suffix-icon': '',
+    maxlength: 11,
+    'show-word-limit': true,
+    readonly: false,
+    disabled: false,
+    required: true,
+    changeTag: true,
+    regList: [{
+      pattern: '/^1(3|4|5|7|8|9)\\d{9}$/',
+      message: '鎵嬫満鍙锋牸寮忛敊璇�'
+    }]
+  }
+]
diff --git a/jcdm-ui/src/utils/generator/html.js b/jcdm-ui/src/utils/generator/html.js
new file mode 100644
index 0000000..9bcc536
--- /dev/null
+++ b/jcdm-ui/src/utils/generator/html.js
@@ -0,0 +1,359 @@
+/* eslint-disable max-len */
+import { trigger } from './config'
+
+let confGlobal
+let someSpanIsNot24
+
+export function dialogWrapper(str) {
+  return `<el-dialog v-bind="$attrs" v-on="$listeners" @open="onOpen" @close="onClose" title="Dialog Title">
+    ${str}
+    <div slot="footer">
+      <el-button @click="close">鍙栨秷</el-button>
+      <el-button type="primary" @click="handleConfirm">纭畾</el-button>
+    </div>
+  </el-dialog>`
+}
+
+export function vueTemplate(str) {
+  return `<template>
+    <div>
+      ${str}
+    </div>
+  </template>`
+}
+
+export function vueScript(str) {
+  return `<script>
+    ${str}
+  </script>`
+}
+
+export function cssStyle(cssStr) {
+  return `<style>
+    ${cssStr}
+  </style>`
+}
+
+function buildFormTemplate(conf, child, type) {
+  let labelPosition = ''
+  if (conf.labelPosition !== 'right') {
+    labelPosition = `label-position="${conf.labelPosition}"`
+  }
+  const disabled = conf.disabled ? `:disabled="${conf.disabled}"` : ''
+  let str = `<el-form ref="${conf.formRef}" :model="${conf.formModel}" :rules="${conf.formRules}" size="${conf.size}" ${disabled} label-width="${conf.labelWidth}px" ${labelPosition}>
+      ${child}
+      ${buildFromBtns(conf, type)}
+    </el-form>`
+  if (someSpanIsNot24) {
+    str = `<el-row :gutter="${conf.gutter}">
+        ${str}
+      </el-row>`
+  }
+  return str
+}
+
+function buildFromBtns(conf, type) {
+  let str = ''
+  if (conf.formBtns && type === 'file') {
+    str = `<el-form-item size="large">
+          <el-button type="primary" @click="submitForm">鎻愪氦</el-button>
+          <el-button @click="resetForm">閲嶇疆</el-button>
+        </el-form-item>`
+    if (someSpanIsNot24) {
+      str = `<el-col :span="24">
+          ${str}
+        </el-col>`
+    }
+  }
+  return str
+}
+
+// span涓嶄负24鐨勭敤el-col鍖呰9
+function colWrapper(element, str) {
+  if (someSpanIsNot24 || element.span !== 24) {
+    return `<el-col :span="${element.span}">
+      ${str}
+    </el-col>`
+  }
+  return str
+}
+
+const layouts = {
+  colFormItem(element) {
+    let labelWidth = ''
+    if (element.labelWidth && element.labelWidth !== confGlobal.labelWidth) {
+      labelWidth = `label-width="${element.labelWidth}px"`
+    }
+    const required = !trigger[element.tag] && element.required ? 'required' : ''
+    const tagDom = tags[element.tag] ? tags[element.tag](element) : null
+    let str = `<el-form-item ${labelWidth} label="${element.label}" prop="${element.vModel}" ${required}>
+        ${tagDom}
+      </el-form-item>`
+    str = colWrapper(element, str)
+    return str
+  },
+  rowFormItem(element) {
+    const type = element.type === 'default' ? '' : `type="${element.type}"`
+    const justify = element.type === 'default' ? '' : `justify="${element.justify}"`
+    const align = element.type === 'default' ? '' : `align="${element.align}"`
+    const gutter = element.gutter ? `gutter="${element.gutter}"` : ''
+    const children = element.children.map(el => layouts[el.layout](el))
+    let str = `<el-row ${type} ${justify} ${align} ${gutter}>
+      ${children.join('\n')}
+    </el-row>`
+    str = colWrapper(element, str)
+    return str
+  }
+}
+
+const tags = {
+  'el-button': el => {
+    const {
+      tag, disabled
+    } = attrBuilder(el)
+    const type = el.type ? `type="${el.type}"` : ''
+    const icon = el.icon ? `icon="${el.icon}"` : ''
+    const size = el.size ? `size="${el.size}"` : ''
+    let child = buildElButtonChild(el)
+
+    if (child) child = `\n${child}\n` // 鎹㈣
+    return `<${el.tag} ${type} ${icon} ${size} ${disabled}>${child}</${el.tag}>`
+  },
+  'el-input': el => {
+    const {
+      disabled, vModel, clearable, placeholder, width
+    } = attrBuilder(el)
+    const maxlength = el.maxlength ? `:maxlength="${el.maxlength}"` : ''
+    const showWordLimit = el['show-word-limit'] ? 'show-word-limit' : ''
+    const readonly = el.readonly ? 'readonly' : ''
+    const prefixIcon = el['prefix-icon'] ? `prefix-icon='${el['prefix-icon']}'` : ''
+    const suffixIcon = el['suffix-icon'] ? `suffix-icon='${el['suffix-icon']}'` : ''
+    const showPassword = el['show-password'] ? 'show-password' : ''
+    const type = el.type ? `type="${el.type}"` : ''
+    const autosize = el.autosize && el.autosize.minRows
+      ? `:autosize="{minRows: ${el.autosize.minRows}, maxRows: ${el.autosize.maxRows}}"`
+      : ''
+    let child = buildElInputChild(el)
+
+    if (child) child = `\n${child}\n` // 鎹㈣
+    return `<${el.tag} ${vModel} ${type} ${placeholder} ${maxlength} ${showWordLimit} ${readonly} ${disabled} ${clearable} ${prefixIcon} ${suffixIcon} ${showPassword} ${autosize} ${width}>${child}</${el.tag}>`
+  },
+  'el-input-number': el => {
+    const { disabled, vModel, placeholder } = attrBuilder(el)
+    const controlsPosition = el['controls-position'] ? `controls-position=${el['controls-position']}` : ''
+    const min = el.min ? `:min='${el.min}'` : ''
+    const max = el.max ? `:max='${el.max}'` : ''
+    const step = el.step ? `:step='${el.step}'` : ''
+    const stepStrictly = el['step-strictly'] ? 'step-strictly' : ''
+    const precision = el.precision ? `:precision='${el.precision}'` : ''
+
+    return `<${el.tag} ${vModel} ${placeholder} ${step} ${stepStrictly} ${precision} ${controlsPosition} ${min} ${max} ${disabled}></${el.tag}>`
+  },
+  'el-select': el => {
+    const {
+      disabled, vModel, clearable, placeholder, width
+    } = attrBuilder(el)
+    const filterable = el.filterable ? 'filterable' : ''
+    const multiple = el.multiple ? 'multiple' : ''
+    let child = buildElSelectChild(el)
+
+    if (child) child = `\n${child}\n` // 鎹㈣
+    return `<${el.tag} ${vModel} ${placeholder} ${disabled} ${multiple} ${filterable} ${clearable} ${width}>${child}</${el.tag}>`
+  },
+  'el-radio-group': el => {
+    const { disabled, vModel } = attrBuilder(el)
+    const size = `size="${el.size}"`
+    let child = buildElRadioGroupChild(el)
+
+    if (child) child = `\n${child}\n` // 鎹㈣
+    return `<${el.tag} ${vModel} ${size} ${disabled}>${child}</${el.tag}>`
+  },
+  'el-checkbox-group': el => {
+    const { disabled, vModel } = attrBuilder(el)
+    const size = `size="${el.size}"`
+    const min = el.min ? `:min="${el.min}"` : ''
+    const max = el.max ? `:max="${el.max}"` : ''
+    let child = buildElCheckboxGroupChild(el)
+
+    if (child) child = `\n${child}\n` // 鎹㈣
+    return `<${el.tag} ${vModel} ${min} ${max} ${size} ${disabled}>${child}</${el.tag}>`
+  },
+  'el-switch': el => {
+    const { disabled, vModel } = attrBuilder(el)
+    const activeText = el['active-text'] ? `active-text="${el['active-text']}"` : ''
+    const inactiveText = el['inactive-text'] ? `inactive-text="${el['inactive-text']}"` : ''
+    const activeColor = el['active-color'] ? `active-color="${el['active-color']}"` : ''
+    const inactiveColor = el['inactive-color'] ? `inactive-color="${el['inactive-color']}"` : ''
+    const activeValue = el['active-value'] !== true ? `:active-value='${JSON.stringify(el['active-value'])}'` : ''
+    const inactiveValue = el['inactive-value'] !== false ? `:inactive-value='${JSON.stringify(el['inactive-value'])}'` : ''
+
+    return `<${el.tag} ${vModel} ${activeText} ${inactiveText} ${activeColor} ${inactiveColor} ${activeValue} ${inactiveValue} ${disabled}></${el.tag}>`
+  },
+  'el-cascader': el => {
+    const {
+      disabled, vModel, clearable, placeholder, width
+    } = attrBuilder(el)
+    const options = el.options ? `:options="${el.vModel}Options"` : ''
+    const props = el.props ? `:props="${el.vModel}Props"` : ''
+    const showAllLevels = el['show-all-levels'] ? '' : ':show-all-levels="false"'
+    const filterable = el.filterable ? 'filterable' : ''
+    const separator = el.separator === '/' ? '' : `separator="${el.separator}"`
+
+    return `<${el.tag} ${vModel} ${options} ${props} ${width} ${showAllLevels} ${placeholder} ${separator} ${filterable} ${clearable} ${disabled}></${el.tag}>`
+  },
+  'el-slider': el => {
+    const { disabled, vModel } = attrBuilder(el)
+    const min = el.min ? `:min='${el.min}'` : ''
+    const max = el.max ? `:max='${el.max}'` : ''
+    const step = el.step ? `:step='${el.step}'` : ''
+    const range = el.range ? 'range' : ''
+    const showStops = el['show-stops'] ? `:show-stops="${el['show-stops']}"` : ''
+
+    return `<${el.tag} ${min} ${max} ${step} ${vModel} ${range} ${showStops} ${disabled}></${el.tag}>`
+  },
+  'el-time-picker': el => {
+    const {
+      disabled, vModel, clearable, placeholder, width
+    } = attrBuilder(el)
+    const startPlaceholder = el['start-placeholder'] ? `start-placeholder="${el['start-placeholder']}"` : ''
+    const endPlaceholder = el['end-placeholder'] ? `end-placeholder="${el['end-placeholder']}"` : ''
+    const rangeSeparator = el['range-separator'] ? `range-separator="${el['range-separator']}"` : ''
+    const isRange = el['is-range'] ? 'is-range' : ''
+    const format = el.format ? `format="${el.format}"` : ''
+    const valueFormat = el['value-format'] ? `value-format="${el['value-format']}"` : ''
+    const pickerOptions = el['picker-options'] ? `:picker-options='${JSON.stringify(el['picker-options'])}'` : ''
+
+    return `<${el.tag} ${vModel} ${isRange} ${format} ${valueFormat} ${pickerOptions} ${width} ${placeholder} ${startPlaceholder} ${endPlaceholder} ${rangeSeparator} ${clearable} ${disabled}></${el.tag}>`
+  },
+  'el-date-picker': el => {
+    const {
+      disabled, vModel, clearable, placeholder, width
+    } = attrBuilder(el)
+    const startPlaceholder = el['start-placeholder'] ? `start-placeholder="${el['start-placeholder']}"` : ''
+    const endPlaceholder = el['end-placeholder'] ? `end-placeholder="${el['end-placeholder']}"` : ''
+    const rangeSeparator = el['range-separator'] ? `range-separator="${el['range-separator']}"` : ''
+    const format = el.format ? `format="${el.format}"` : ''
+    const valueFormat = el['value-format'] ? `value-format="${el['value-format']}"` : ''
+    const type = el.type === 'date' ? '' : `type="${el.type}"`
+    const readonly = el.readonly ? 'readonly' : ''
+
+    return `<${el.tag} ${type} ${vModel} ${format} ${valueFormat} ${width} ${placeholder} ${startPlaceholder} ${endPlaceholder} ${rangeSeparator} ${clearable} ${readonly} ${disabled}></${el.tag}>`
+  },
+  'el-rate': el => {
+    const { disabled, vModel } = attrBuilder(el)
+    const max = el.max ? `:max='${el.max}'` : ''
+    const allowHalf = el['allow-half'] ? 'allow-half' : ''
+    const showText = el['show-text'] ? 'show-text' : ''
+    const showScore = el['show-score'] ? 'show-score' : ''
+
+    return `<${el.tag} ${vModel} ${allowHalf} ${showText} ${showScore} ${disabled}></${el.tag}>`
+  },
+  'el-color-picker': el => {
+    const { disabled, vModel } = attrBuilder(el)
+    const size = `size="${el.size}"`
+    const showAlpha = el['show-alpha'] ? 'show-alpha' : ''
+    const colorFormat = el['color-format'] ? `color-format="${el['color-format']}"` : ''
+
+    return `<${el.tag} ${vModel} ${size} ${showAlpha} ${colorFormat} ${disabled}></${el.tag}>`
+  },
+  'el-upload': el => {
+    const disabled = el.disabled ? ':disabled=\'true\'' : ''
+    const action = el.action ? `:action="${el.vModel}Action"` : ''
+    const multiple = el.multiple ? 'multiple' : ''
+    const listType = el['list-type'] !== 'text' ? `list-type="${el['list-type']}"` : ''
+    const accept = el.accept ? `accept="${el.accept}"` : ''
+    const name = el.name !== 'file' ? `name="${el.name}"` : ''
+    const autoUpload = el['auto-upload'] === false ? ':auto-upload="false"' : ''
+    const beforeUpload = `:before-upload="${el.vModel}BeforeUpload"`
+    const fileList = `:file-list="${el.vModel}fileList"`
+    const ref = `ref="${el.vModel}"`
+    let child = buildElUploadChild(el)
+
+    if (child) child = `\n${child}\n` // 鎹㈣
+    return `<${el.tag} ${ref} ${fileList} ${action} ${autoUpload} ${multiple} ${beforeUpload} ${listType} ${accept} ${name} ${disabled}>${child}</${el.tag}>`
+  }
+}
+
+function attrBuilder(el) {
+  return {
+    vModel: `v-model="${confGlobal.formModel}.${el.vModel}"`,
+    clearable: el.clearable ? 'clearable' : '',
+    placeholder: el.placeholder ? `placeholder="${el.placeholder}"` : '',
+    width: el.style && el.style.width ? ':style="{width: \'100%\'}"' : '',
+    disabled: el.disabled ? ':disabled=\'true\'' : ''
+  }
+}
+
+// el-buttin 瀛愮骇
+function buildElButtonChild(conf) {
+  const children = []
+  if (conf.default) {
+    children.push(conf.default)
+  }
+  return children.join('\n')
+}
+
+// el-input innerHTML
+function buildElInputChild(conf) {
+  const children = []
+  if (conf.prepend) {
+    children.push(`<template slot="prepend">${conf.prepend}</template>`)
+  }
+  if (conf.append) {
+    children.push(`<template slot="append">${conf.append}</template>`)
+  }
+  return children.join('\n')
+}
+
+function buildElSelectChild(conf) {
+  const children = []
+  if (conf.options && conf.options.length) {
+    children.push(`<el-option v-for="(item, index) in ${conf.vModel}Options" :key="index" :label="item.label" :value="item.value" :disabled="item.disabled"></el-option>`)
+  }
+  return children.join('\n')
+}
+
+function buildElRadioGroupChild(conf) {
+  const children = []
+  if (conf.options && conf.options.length) {
+    const tag = conf.optionType === 'button' ? 'el-radio-button' : 'el-radio'
+    const border = conf.border ? 'border' : ''
+    children.push(`<${tag} v-for="(item, index) in ${conf.vModel}Options" :key="index" :label="item.value" :disabled="item.disabled" ${border}>{{item.label}}</${tag}>`)
+  }
+  return children.join('\n')
+}
+
+function buildElCheckboxGroupChild(conf) {
+  const children = []
+  if (conf.options && conf.options.length) {
+    const tag = conf.optionType === 'button' ? 'el-checkbox-button' : 'el-checkbox'
+    const border = conf.border ? 'border' : ''
+    children.push(`<${tag} v-for="(item, index) in ${conf.vModel}Options" :key="index" :label="item.value" :disabled="item.disabled" ${border}>{{item.label}}</${tag}>`)
+  }
+  return children.join('\n')
+}
+
+function buildElUploadChild(conf) {
+  const list = []
+  if (conf['list-type'] === 'picture-card') list.push('<i class="el-icon-plus"></i>')
+  else list.push(`<el-button size="small" type="primary" icon="el-icon-upload">${conf.buttonText}</el-button>`)
+  if (conf.showTip) list.push(`<div slot="tip" class="el-upload__tip">鍙兘涓婁紶涓嶈秴杩� ${conf.fileSize}${conf.sizeUnit} 鐨�${conf.accept}鏂囦欢</div>`)
+  return list.join('\n')
+}
+
+export function makeUpHtml(conf, type) {
+  const htmlList = []
+  confGlobal = conf
+  someSpanIsNot24 = conf.fields.some(item => item.span !== 24)
+  conf.fields.forEach(el => {
+    htmlList.push(layouts[el.layout](el))
+  })
+  const htmlStr = htmlList.join('\n')
+
+  let temp = buildFormTemplate(conf, htmlStr, type)
+  if (type === 'dialog') {
+    temp = dialogWrapper(temp)
+  }
+  confGlobal = null
+  return temp
+}
diff --git a/jcdm-ui/src/utils/generator/icon.json b/jcdm-ui/src/utils/generator/icon.json
new file mode 100644
index 0000000..2d9999a
--- /dev/null
+++ b/jcdm-ui/src/utils/generator/icon.json
@@ -0,0 +1 @@
+["platform-eleme","eleme","delete-solid","delete","s-tools","setting","user-solid","user","phone","phone-outline","more","more-outline","star-on","star-off","s-goods","goods","warning","warning-outline","question","info","remove","circle-plus","success","error","zoom-in","zoom-out","remove-outline","circle-plus-outline","circle-check","circle-close","s-help","help","minus","plus","check","close","picture","picture-outline","picture-outline-round","upload","upload2","download","camera-solid","camera","video-camera-solid","video-camera","message-solid","bell","s-cooperation","s-order","s-platform","s-fold","s-unfold","s-operation","s-promotion","s-home","s-release","s-ticket","s-management","s-open","s-shop","s-marketing","s-flag","s-comment","s-finance","s-claim","s-custom","s-opportunity","s-data","s-check","s-grid","menu","share","d-caret","caret-left","caret-right","caret-bottom","caret-top","bottom-left","bottom-right","back","right","bottom","top","top-left","top-right","arrow-left","arrow-right","arrow-down","arrow-up","d-arrow-left","d-arrow-right","video-pause","video-play","refresh","refresh-right","refresh-left","finished","sort","sort-up","sort-down","rank","loading","view","c-scale-to-original","date","edit","edit-outline","folder","folder-opened","folder-add","folder-remove","folder-delete","folder-checked","tickets","document-remove","document-delete","document-copy","document-checked","document","document-add","printer","paperclip","takeaway-box","search","monitor","attract","mobile","scissors","umbrella","headset","brush","mouse","coordinate","magic-stick","reading","data-line","data-board","pie-chart","data-analysis","collection-tag","film","suitcase","suitcase-1","receiving","collection","files","notebook-1","notebook-2","toilet-paper","office-building","school","table-lamp","house","no-smoking","smoking","shopping-cart-full","shopping-cart-1","shopping-cart-2","shopping-bag-1","shopping-bag-2","sold-out","sell","present","box","bank-card","money","coin","wallet","discount","price-tag","news","guide","male","female","thumb","cpu","link","connection","open","turn-off","set-up","chat-round","chat-line-round","chat-square","chat-dot-round","chat-dot-square","chat-line-square","message","postcard","position","turn-off-microphone","microphone","close-notification","bangzhu","time","odometer","crop","aim","switch-button","full-screen","copy-document","mic","stopwatch","medal-1","medal","trophy","trophy-1","first-aid-kit","discover","place","location","location-outline","location-information","add-location","delete-location","map-location","alarm-clock","timer","watch-1","watch","lock","unlock","key","service","mobile-phone","bicycle","truck","ship","basketball","football","soccer","baseball","wind-power","light-rain","lightning","heavy-rain","sunrise","sunrise-1","sunset","sunny","cloudy","partly-cloudy","cloudy-and-sunny","moon","moon-night","dish","dish-1","food","chicken","fork-spoon","knife-fork","burger","tableware","sugar","dessert","ice-cream","hot-water","water-cup","coffee-cup","cold-drink","goblet","goblet-full","goblet-square","goblet-square-full","refrigerator","grape","watermelon","cherry","apple","pear","orange","coffee","ice-tea","ice-drink","milk-tea","potato-strips","lollipop","ice-cream-square","ice-cream-round"]
\ No newline at end of file
diff --git a/jcdm-ui/src/utils/generator/js.js b/jcdm-ui/src/utils/generator/js.js
new file mode 100644
index 0000000..ee8668d
--- /dev/null
+++ b/jcdm-ui/src/utils/generator/js.js
@@ -0,0 +1,235 @@
+import { exportDefault, titleCase } from '@/utils/index'
+import { trigger } from './config'
+
+const units = {
+  KB: '1024',
+  MB: '1024 / 1024',
+  GB: '1024 / 1024 / 1024'
+}
+let confGlobal
+const inheritAttrs = {
+  file: '',
+  dialog: 'inheritAttrs: false,'
+}
+
+
+export function makeUpJs(conf, type) {
+  confGlobal = conf = JSON.parse(JSON.stringify(conf))
+  const dataList = []
+  const ruleList = []
+  const optionsList = []
+  const propsList = []
+  const methodList = mixinMethod(type)
+  const uploadVarList = []
+
+  conf.fields.forEach(el => {
+    buildAttributes(el, dataList, ruleList, optionsList, methodList, propsList, uploadVarList)
+  })
+
+  const script = buildexport(
+    conf,
+    type,
+    dataList.join('\n'),
+    ruleList.join('\n'),
+    optionsList.join('\n'),
+    uploadVarList.join('\n'),
+    propsList.join('\n'),
+    methodList.join('\n')
+  )
+  confGlobal = null
+  return script
+}
+
+function buildAttributes(el, dataList, ruleList, optionsList, methodList, propsList, uploadVarList) {
+  buildData(el, dataList)
+  buildRules(el, ruleList)
+
+  if (el.options && el.options.length) {
+    buildOptions(el, optionsList)
+    if (el.dataType === 'dynamic') {
+      const model = `${el.vModel}Options`
+      const options = titleCase(model)
+      buildOptionMethod(`get${options}`, model, methodList)
+    }
+  }
+
+  if (el.props && el.props.props) {
+    buildProps(el, propsList)
+  }
+
+  if (el.action && el.tag === 'el-upload') {
+    uploadVarList.push(
+      `${el.vModel}Action: '${el.action}',
+      ${el.vModel}fileList: [],`
+    )
+    methodList.push(buildBeforeUpload(el))
+    if (!el['auto-upload']) {
+      methodList.push(buildSubmitUpload(el))
+    }
+  }
+
+  if (el.children) {
+    el.children.forEach(el2 => {
+      buildAttributes(el2, dataList, ruleList, optionsList, methodList, propsList, uploadVarList)
+    })
+  }
+}
+
+function mixinMethod(type) {
+  const list = []; const
+    minxins = {
+      file: confGlobal.formBtns ? {
+        submitForm: `submitForm() {
+        this.$refs['${confGlobal.formRef}'].validate(valid => {
+          if(!valid) return
+          // TODO 鎻愪氦琛ㄥ崟
+        })
+      },`,
+        resetForm: `resetForm() {
+        this.$refs['${confGlobal.formRef}'].resetFields()
+      },`
+      } : null,
+      dialog: {
+        onOpen: 'onOpen() {},',
+        onClose: `onClose() {
+        this.$refs['${confGlobal.formRef}'].resetFields()
+      },`,
+        close: `close() {
+        this.$emit('update:visible', false)
+      },`,
+        handleConfirm: `handleConfirm() {
+        this.$refs['${confGlobal.formRef}'].validate(valid => {
+          if(!valid) return
+          this.close()
+        })
+      },`
+      }
+    }
+
+  const methods = minxins[type]
+  if (methods) {
+    Object.keys(methods).forEach(key => {
+      list.push(methods[key])
+    })
+  }
+
+  return list
+}
+
+function buildData(conf, dataList) {
+  if (conf.vModel === undefined) return
+  let defaultValue
+  if (typeof (conf.defaultValue) === 'string' && !conf.multiple) {
+    defaultValue = `'${conf.defaultValue}'`
+  } else {
+    defaultValue = `${JSON.stringify(conf.defaultValue)}`
+  }
+  dataList.push(`${conf.vModel}: ${defaultValue},`)
+}
+
+function buildRules(conf, ruleList) {
+  if (conf.vModel === undefined) return
+  const rules = []
+  if (trigger[conf.tag]) {
+    if (conf.required) {
+      const type = Array.isArray(conf.defaultValue) ? 'type: \'array\',' : ''
+      let message = Array.isArray(conf.defaultValue) ? `璇疯嚦灏戦�夋嫨涓�涓�${conf.vModel}` : conf.placeholder
+      if (message === undefined) message = `${conf.label}涓嶈兘涓虹┖`
+      rules.push(`{ required: true, ${type} message: '${message}', trigger: '${trigger[conf.tag]}' }`)
+    }
+    if (conf.regList && Array.isArray(conf.regList)) {
+      conf.regList.forEach(item => {
+        if (item.pattern) {
+          rules.push(`{ pattern: ${eval(item.pattern)}, message: '${item.message}', trigger: '${trigger[conf.tag]}' }`)
+        }
+      })
+    }
+    ruleList.push(`${conf.vModel}: [${rules.join(',')}],`)
+  }
+}
+
+function buildOptions(conf, optionsList) {
+  if (conf.vModel === undefined) return
+  if (conf.dataType === 'dynamic') { conf.options = [] }
+  const str = `${conf.vModel}Options: ${JSON.stringify(conf.options)},`
+  optionsList.push(str)
+}
+
+function buildProps(conf, propsList) {
+  if (conf.dataType === 'dynamic') {
+    conf.valueKey !== 'value' && (conf.props.props.value = conf.valueKey)
+    conf.labelKey !== 'label' && (conf.props.props.label = conf.labelKey)
+    conf.childrenKey !== 'children' && (conf.props.props.children = conf.childrenKey)
+  }
+  const str = `${conf.vModel}Props: ${JSON.stringify(conf.props.props)},`
+  propsList.push(str)
+}
+
+function buildBeforeUpload(conf) {
+  const unitNum = units[conf.sizeUnit]; let rightSizeCode = ''; let acceptCode = ''; const
+    returnList = []
+  if (conf.fileSize) {
+    rightSizeCode = `let isRightSize = file.size / ${unitNum} < ${conf.fileSize}
+    if(!isRightSize){
+      this.$message.error('鏂囦欢澶у皬瓒呰繃 ${conf.fileSize}${conf.sizeUnit}')
+    }`
+    returnList.push('isRightSize')
+  }
+  if (conf.accept) {
+    acceptCode = `let isAccept = new RegExp('${conf.accept}').test(file.type)
+    if(!isAccept){
+      this.$message.error('搴旇閫夋嫨${conf.accept}绫诲瀷鐨勬枃浠�')
+    }`
+    returnList.push('isAccept')
+  }
+  const str = `${conf.vModel}BeforeUpload(file) {
+    ${rightSizeCode}
+    ${acceptCode}
+    return ${returnList.join('&&')}
+  },`
+  return returnList.length ? str : ''
+}
+
+function buildSubmitUpload(conf) {
+  const str = `submitUpload() {
+    this.$refs['${conf.vModel}'].submit()
+  },`
+  return str
+}
+
+function buildOptionMethod(methodName, model, methodList) {
+  const str = `${methodName}() {
+    // TODO 鍙戣捣璇锋眰鑾峰彇鏁版嵁
+    this.${model}
+  },`
+  methodList.push(str)
+}
+
+function buildexport(conf, type, data, rules, selectOptions, uploadVar, props, methods) {
+  const str = `${exportDefault}{
+  ${inheritAttrs[type]}
+  components: {},
+  props: [],
+  data () {
+    return {
+      ${conf.formModel}: {
+        ${data}
+      },
+      ${conf.formRules}: {
+        ${rules}
+      },
+      ${uploadVar}
+      ${selectOptions}
+      ${props}
+    }
+  },
+  computed: {},
+  watch: {},
+  created () {},
+  mounted () {},
+  methods: {
+    ${methods}
+  }
+}`
+  return str
+}
diff --git a/jcdm-ui/src/utils/generator/render.js b/jcdm-ui/src/utils/generator/render.js
new file mode 100644
index 0000000..e8640f0
--- /dev/null
+++ b/jcdm-ui/src/utils/generator/render.js
@@ -0,0 +1,126 @@
+import { makeMap } from '@/utils/index'
+
+// 鍙傝�僪ttps://github.com/vuejs/vue/blob/v2.6.10/src/platforms/web/server/util.js
+const isAttr = makeMap(
+  'accept,accept-charset,accesskey,action,align,alt,async,autocomplete,'
+  + 'autofocus,autoplay,autosave,bgcolor,border,buffered,challenge,charset,'
+  + 'checked,cite,class,code,codebase,color,cols,colspan,content,http-equiv,'
+  + 'name,contenteditable,contextmenu,controls,coords,data,datetime,default,'
+  + 'defer,dir,dirname,disabled,download,draggable,dropzone,enctype,method,for,'
+  + 'form,formaction,headers,height,hidden,high,href,hreflang,http-equiv,'
+  + 'icon,id,ismap,itemprop,keytype,kind,label,lang,language,list,loop,low,'
+  + 'manifest,max,maxlength,media,method,GET,POST,min,multiple,email,file,'
+  + 'muted,name,novalidate,open,optimum,pattern,ping,placeholder,poster,'
+  + 'preload,radiogroup,readonly,rel,required,reversed,rows,rowspan,sandbox,'
+  + 'scope,scoped,seamless,selected,shape,size,type,text,password,sizes,span,'
+  + 'spellcheck,src,srcdoc,srclang,srcset,start,step,style,summary,tabindex,'
+  + 'target,title,type,usemap,value,width,wrap'
+)
+
+function vModel(self, dataObject, defaultValue) {
+  dataObject.props.value = defaultValue
+
+  dataObject.on.input = val => {
+    self.$emit('input', val)
+  }
+}
+
+const componentChild = {
+  'el-button': {
+    default(h, conf, key) {
+      return conf[key]
+    },
+  },
+  'el-input': {
+    prepend(h, conf, key) {
+      return <template slot="prepend">{conf[key]}</template>
+    },
+    append(h, conf, key) {
+      return <template slot="append">{conf[key]}</template>
+    }
+  },
+  'el-select': {
+    options(h, conf, key) {
+      const list = []
+      conf.options.forEach(item => {
+        list.push(<el-option label={item.label} value={item.value} disabled={item.disabled}></el-option>)
+      })
+      return list
+    }
+  },
+  'el-radio-group': {
+    options(h, conf, key) {
+      const list = []
+      conf.options.forEach(item => {
+        if (conf.optionType === 'button') list.push(<el-radio-button label={item.value}>{item.label}</el-radio-button>)
+        else list.push(<el-radio label={item.value} border={conf.border}>{item.label}</el-radio>)
+      })
+      return list
+    }
+  },
+  'el-checkbox-group': {
+    options(h, conf, key) {
+      const list = []
+      conf.options.forEach(item => {
+        if (conf.optionType === 'button') {
+          list.push(<el-checkbox-button label={item.value}>{item.label}</el-checkbox-button>)
+        } else {
+          list.push(<el-checkbox label={item.value} border={conf.border}>{item.label}</el-checkbox>)
+        }
+      })
+      return list
+    }
+  },
+  'el-upload': {
+    'list-type': (h, conf, key) => {
+      const list = []
+      if (conf['list-type'] === 'picture-card') {
+        list.push(<i class="el-icon-plus"></i>)
+      } else {
+        list.push(<el-button size="small" type="primary" icon="el-icon-upload">{conf.buttonText}</el-button>)
+      }
+      if (conf.showTip) {
+        list.push(<div slot="tip" class="el-upload__tip">鍙兘涓婁紶涓嶈秴杩� {conf.fileSize}{conf.sizeUnit} 鐨剓conf.accept}鏂囦欢</div>)
+      }
+      return list
+    }
+  }
+}
+
+export default {
+  render(h) {
+    const dataObject = {
+      attrs: {},
+      props: {},
+      on: {},
+      style: {}
+    }
+    const confClone = JSON.parse(JSON.stringify(this.conf))
+    const children = []
+
+    const childObjs = componentChild[confClone.tag]
+    if (childObjs) {
+      Object.keys(childObjs).forEach(key => {
+        const childFunc = childObjs[key]
+        if (confClone[key]) {
+          children.push(childFunc(h, confClone, key))
+        }
+      })
+    }
+
+    Object.keys(confClone).forEach(key => {
+      const val = confClone[key]
+      if (key === 'vModel') {
+        vModel(this, dataObject, confClone.defaultValue)
+      } else if (dataObject[key]) {
+        dataObject[key] = val
+      } else if (!isAttr(key)) {
+        dataObject.props[key] = val
+      } else {
+        dataObject.attrs[key] = val
+      }
+    })
+    return h(this.conf.tag, dataObject, children)
+  },
+  props: ['conf']
+}
diff --git a/jcdm-ui/src/utils/index.js b/jcdm-ui/src/utils/index.js
new file mode 100644
index 0000000..df5db12
--- /dev/null
+++ b/jcdm-ui/src/utils/index.js
@@ -0,0 +1,390 @@
+import { parseTime } from './ruoyi'
+
+/**
+ * 琛ㄦ牸鏃堕棿鏍煎紡鍖�
+ */
+export function formatDate(cellValue) {
+  if (cellValue == null || cellValue == "") return "";
+  var date = new Date(cellValue)
+  var year = date.getFullYear()
+  var month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1
+  var day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate()
+  var hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours()
+  var minutes = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()
+  var seconds = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()
+  return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds
+}
+
+/**
+ * @param {number} time
+ * @param {string} option
+ * @returns {string}
+ */
+export function formatTime(time, option) {
+  if (('' + time).length === 10) {
+    time = parseInt(time) * 1000
+  } else {
+    time = +time
+  }
+  const d = new Date(time)
+  const now = Date.now()
+
+  const diff = (now - d) / 1000
+
+  if (diff < 30) {
+    return '鍒氬垰'
+  } else if (diff < 3600) {
+    // less 1 hour
+    return Math.ceil(diff / 60) + '鍒嗛挓鍓�'
+  } else if (diff < 3600 * 24) {
+    return Math.ceil(diff / 3600) + '灏忔椂鍓�'
+  } else if (diff < 3600 * 24 * 2) {
+    return '1澶╁墠'
+  }
+  if (option) {
+    return parseTime(time, option)
+  } else {
+    return (
+      d.getMonth() +
+      1 +
+      '鏈�' +
+      d.getDate() +
+      '鏃�' +
+      d.getHours() +
+      '鏃�' +
+      d.getMinutes() +
+      '鍒�'
+    )
+  }
+}
+
+/**
+ * @param {string} url
+ * @returns {Object}
+ */
+export function getQueryObject(url) {
+  url = url == null ? window.location.href : url
+  const search = url.substring(url.lastIndexOf('?') + 1)
+  const obj = {}
+  const reg = /([^?&=]+)=([^?&=]*)/g
+  search.replace(reg, (rs, $1, $2) => {
+    const name = decodeURIComponent($1)
+    let val = decodeURIComponent($2)
+    val = String(val)
+    obj[name] = val
+    return rs
+  })
+  return obj
+}
+
+/**
+ * @param {string} input value
+ * @returns {number} output value
+ */
+export function byteLength(str) {
+  // returns the byte length of an utf8 string
+  let s = str.length
+  for (var i = str.length - 1; i >= 0; i--) {
+    const code = str.charCodeAt(i)
+    if (code > 0x7f && code <= 0x7ff) s++
+    else if (code > 0x7ff && code <= 0xffff) s += 2
+    if (code >= 0xDC00 && code <= 0xDFFF) i--
+  }
+  return s
+}
+
+/**
+ * @param {Array} actual
+ * @returns {Array}
+ */
+export function cleanArray(actual) {
+  const newArray = []
+  for (let i = 0; i < actual.length; i++) {
+    if (actual[i]) {
+      newArray.push(actual[i])
+    }
+  }
+  return newArray
+}
+
+/**
+ * @param {Object} json
+ * @returns {Array}
+ */
+export function param(json) {
+  if (!json) return ''
+  return cleanArray(
+    Object.keys(json).map(key => {
+      if (json[key] === undefined) return ''
+      return encodeURIComponent(key) + '=' + encodeURIComponent(json[key])
+    })
+  ).join('&')
+}
+
+/**
+ * @param {string} url
+ * @returns {Object}
+ */
+export function param2Obj(url) {
+  const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ')
+  if (!search) {
+    return {}
+  }
+  const obj = {}
+  const searchArr = search.split('&')
+  searchArr.forEach(v => {
+    const index = v.indexOf('=')
+    if (index !== -1) {
+      const name = v.substring(0, index)
+      const val = v.substring(index + 1, v.length)
+      obj[name] = val
+    }
+  })
+  return obj
+}
+
+/**
+ * @param {string} val
+ * @returns {string}
+ */
+export function html2Text(val) {
+  const div = document.createElement('div')
+  div.innerHTML = val
+  return div.textContent || div.innerText
+}
+
+/**
+ * Merges two objects, giving the last one precedence
+ * @param {Object} target
+ * @param {(Object|Array)} source
+ * @returns {Object}
+ */
+export function objectMerge(target, source) {
+  if (typeof target !== 'object') {
+    target = {}
+  }
+  if (Array.isArray(source)) {
+    return source.slice()
+  }
+  Object.keys(source).forEach(property => {
+    const sourceProperty = source[property]
+    if (typeof sourceProperty === 'object') {
+      target[property] = objectMerge(target[property], sourceProperty)
+    } else {
+      target[property] = sourceProperty
+    }
+  })
+  return target
+}
+
+/**
+ * @param {HTMLElement} element
+ * @param {string} className
+ */
+export function toggleClass(element, className) {
+  if (!element || !className) {
+    return
+  }
+  let classString = element.className
+  const nameIndex = classString.indexOf(className)
+  if (nameIndex === -1) {
+    classString += '' + className
+  } else {
+    classString =
+      classString.substr(0, nameIndex) +
+      classString.substr(nameIndex + className.length)
+  }
+  element.className = classString
+}
+
+/**
+ * @param {string} type
+ * @returns {Date}
+ */
+export function getTime(type) {
+  if (type === 'start') {
+    return new Date().getTime() - 3600 * 1000 * 24 * 90
+  } else {
+    return new Date(new Date().toDateString())
+  }
+}
+
+/**
+ * @param {Function} func
+ * @param {number} wait
+ * @param {boolean} immediate
+ * @return {*}
+ */
+export function debounce(func, wait, immediate) {
+  let timeout, args, context, timestamp, result
+
+  const later = function() {
+    // 鎹笂涓�娆¤Е鍙戞椂闂撮棿闅�
+    const last = +new Date() - timestamp
+
+    // 涓婃琚寘瑁呭嚱鏁拌璋冪敤鏃堕棿闂撮殧 last 灏忎簬璁惧畾鏃堕棿闂撮殧 wait
+    if (last < wait && last > 0) {
+      timeout = setTimeout(later, wait - last)
+    } else {
+      timeout = null
+      // 濡傛灉璁惧畾涓篿mmediate===true锛屽洜涓哄紑濮嬭竟鐣屽凡缁忚皟鐢ㄨ繃浜嗘澶勬棤闇�璋冪敤
+      if (!immediate) {
+        result = func.apply(context, args)
+        if (!timeout) context = args = null
+      }
+    }
+  }
+
+  return function(...args) {
+    context = this
+    timestamp = +new Date()
+    const callNow = immediate && !timeout
+    // 濡傛灉寤舵椂涓嶅瓨鍦紝閲嶆柊璁惧畾寤舵椂
+    if (!timeout) timeout = setTimeout(later, wait)
+    if (callNow) {
+      result = func.apply(context, args)
+      context = args = null
+    }
+
+    return result
+  }
+}
+
+/**
+ * This is just a simple version of deep copy
+ * Has a lot of edge cases bug
+ * If you want to use a perfect deep copy, use lodash's _.cloneDeep
+ * @param {Object} source
+ * @returns {Object}
+ */
+export function deepClone(source) {
+  if (!source && typeof source !== 'object') {
+    throw new Error('error arguments', 'deepClone')
+  }
+  const targetObj = source.constructor === Array ? [] : {}
+  Object.keys(source).forEach(keys => {
+    if (source[keys] && typeof source[keys] === 'object') {
+      targetObj[keys] = deepClone(source[keys])
+    } else {
+      targetObj[keys] = source[keys]
+    }
+  })
+  return targetObj
+}
+
+/**
+ * @param {Array} arr
+ * @returns {Array}
+ */
+export function uniqueArr(arr) {
+  return Array.from(new Set(arr))
+}
+
+/**
+ * @returns {string}
+ */
+export function createUniqueString() {
+  const timestamp = +new Date() + ''
+  const randomNum = parseInt((1 + Math.random()) * 65536) + ''
+  return (+(randomNum + timestamp)).toString(32)
+}
+
+/**
+ * Check if an element has a class
+ * @param {HTMLElement} elm
+ * @param {string} cls
+ * @returns {boolean}
+ */
+export function hasClass(ele, cls) {
+  return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'))
+}
+
+/**
+ * Add class to element
+ * @param {HTMLElement} elm
+ * @param {string} cls
+ */
+export function addClass(ele, cls) {
+  if (!hasClass(ele, cls)) ele.className += ' ' + cls
+}
+
+/**
+ * Remove class from element
+ * @param {HTMLElement} elm
+ * @param {string} cls
+ */
+export function removeClass(ele, cls) {
+  if (hasClass(ele, cls)) {
+    const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)')
+    ele.className = ele.className.replace(reg, ' ')
+  }
+}
+
+export function makeMap(str, expectsLowerCase) {
+  const map = Object.create(null)
+  const list = str.split(',')
+  for (let i = 0; i < list.length; i++) {
+    map[list[i]] = true
+  }
+  return expectsLowerCase
+    ? val => map[val.toLowerCase()]
+    : val => map[val]
+}
+
+export const exportDefault = 'export default '
+
+export const beautifierConf = {
+  html: {
+    indent_size: '2',
+    indent_char: ' ',
+    max_preserve_newlines: '-1',
+    preserve_newlines: false,
+    keep_array_indentation: false,
+    break_chained_methods: false,
+    indent_scripts: 'separate',
+    brace_style: 'end-expand',
+    space_before_conditional: true,
+    unescape_strings: false,
+    jslint_happy: false,
+    end_with_newline: true,
+    wrap_line_length: '110',
+    indent_inner_html: true,
+    comma_first: false,
+    e4x: true,
+    indent_empty_lines: true
+  },
+  js: {
+    indent_size: '2',
+    indent_char: ' ',
+    max_preserve_newlines: '-1',
+    preserve_newlines: false,
+    keep_array_indentation: false,
+    break_chained_methods: false,
+    indent_scripts: 'normal',
+    brace_style: 'end-expand',
+    space_before_conditional: true,
+    unescape_strings: false,
+    jslint_happy: true,
+    end_with_newline: true,
+    wrap_line_length: '110',
+    indent_inner_html: true,
+    comma_first: false,
+    e4x: true,
+    indent_empty_lines: true
+  }
+}
+
+// 棣栧瓧姣嶅ぇ灏�
+export function titleCase(str) {
+  return str.replace(/( |^)[a-z]/g, L => L.toUpperCase())
+}
+
+// 涓嬪垝杞┘宄�
+export function camelCase(str) {
+  return str.replace(/_[a-z]/g, str1 => str1.substr(-1).toUpperCase())
+}
+
+export function isNumberStr(str) {
+  return /^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(str)
+}
+
diff --git a/jcdm-ui/src/utils/jsencrypt.js b/jcdm-ui/src/utils/jsencrypt.js
new file mode 100644
index 0000000..78d9523
--- /dev/null
+++ b/jcdm-ui/src/utils/jsencrypt.js
@@ -0,0 +1,30 @@
+import JSEncrypt from 'jsencrypt/bin/jsencrypt.min'
+
+// 瀵嗛挜瀵圭敓鎴� http://web.chacuo.net/netrsakeypair
+
+const publicKey = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdH\n' +
+  'nzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
+
+const privateKey = 'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY\n' +
+  '7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKN\n' +
+  'PuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gA\n' +
+  'kM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWow\n' +
+  'cSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99Ecv\n' +
+  'DQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthh\n' +
+  'YhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3\n' +
+  'UP8iWi1Qw0Y='
+
+// 鍔犲瘑
+export function encrypt(txt) {
+  const encryptor = new JSEncrypt()
+  encryptor.setPublicKey(publicKey) // 璁剧疆鍏挜
+  return encryptor.encrypt(txt) // 瀵规暟鎹繘琛屽姞瀵�
+}
+
+// 瑙e瘑
+export function decrypt(txt) {
+  const encryptor = new JSEncrypt()
+  encryptor.setPrivateKey(privateKey) // 璁剧疆绉侀挜
+  return encryptor.decrypt(txt) // 瀵规暟鎹繘琛岃В瀵�
+}
+
diff --git a/jcdm-ui/src/utils/permission.js b/jcdm-ui/src/utils/permission.js
new file mode 100644
index 0000000..189a716
--- /dev/null
+++ b/jcdm-ui/src/utils/permission.js
@@ -0,0 +1,47 @@
+import store from '@/store'
+
+/**
+ * 瀛楃鏉冮檺鏍¢獙
+ * @param {Array} value 鏍¢獙鍊�
+ * @returns {Boolean}
+ */
+export function checkPermi(value) {
+  if (value && value instanceof Array && value.length > 0) {
+    const permissions = store.getters && store.getters.permissions
+    const permissionDatas = value
+    const all_permission = "*:*:*";
+
+    const hasPermission = permissions.some(permission => {
+      return all_permission === permission || permissionDatas.includes(permission)
+    })
+
+    return hasPermission;
+
+  } else {
+    console.error(`need roles! Like checkPermi="['system:user:add','system:user:edit']"`)
+    return false
+  }
+}
+
+/**
+ * 瑙掕壊鏉冮檺鏍¢獙
+ * @param {Array} value 鏍¢獙鍊�
+ * @returns {Boolean}
+ */
+export function checkRole(value) {
+  if (value && value instanceof Array && value.length > 0) {
+    const roles = store.getters && store.getters.roles
+    const permissionRoles = value
+    const super_admin = "admin";
+
+    const hasRole = roles.some(role => {
+      return super_admin === role || permissionRoles.includes(role)
+    })
+
+    return hasRole;
+
+  } else {
+    console.error(`need roles! Like checkRole="['admin','editor']"`)
+    return false
+  }
+}
\ No newline at end of file
diff --git a/jcdm-ui/src/utils/request.js b/jcdm-ui/src/utils/request.js
new file mode 100644
index 0000000..ffb0d21
--- /dev/null
+++ b/jcdm-ui/src/utils/request.js
@@ -0,0 +1,152 @@
+import axios from 'axios'
+import { Notification, MessageBox, Message, Loading } from 'element-ui'
+import store from '@/store'
+import { getToken } from '@/utils/auth'
+import errorCode from '@/utils/errorCode'
+import { tansParams, blobValidate } from "@/utils/ruoyi";
+import cache from '@/plugins/cache'
+import { saveAs } from 'file-saver'
+
+let downloadLoadingInstance;
+// 鏄惁鏄剧ず閲嶆柊鐧诲綍
+export let isRelogin = { show: false };
+
+axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
+// 鍒涘缓axios瀹炰緥
+const service = axios.create({
+  // axios涓姹傞厤缃湁baseURL閫夐」锛岃〃绀鸿姹俇RL鍏叡閮ㄥ垎
+  baseURL: process.env.VUE_APP_BASE_API,
+  // 瓒呮椂
+  timeout: 10000
+})
+
+// request鎷︽埅鍣�
+service.interceptors.request.use(config => {
+  // 鏄惁闇�瑕佽缃� token
+  const isToken = (config.headers || {}).isToken === false
+  // 鏄惁闇�瑕侀槻姝㈡暟鎹噸澶嶆彁浜�
+  const isRepeatSubmit = (config.headers || {}).repeatSubmit === false
+  if (getToken() && !isToken) {
+    config.headers['Authorization'] = 'Bearer ' + getToken() // 璁╂瘡涓姹傛惡甯﹁嚜瀹氫箟token 璇锋牴鎹疄闄呮儏鍐佃嚜琛屼慨鏀�
+  }
+  // get璇锋眰鏄犲皠params鍙傛暟
+  if (config.method === 'get' && config.params) {
+    let url = config.url + '?' + tansParams(config.params);
+    url = url.slice(0, -1);
+    config.params = {};
+    config.url = url;
+  }
+  if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
+    const requestObj = {
+      url: config.url,
+      data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
+      time: new Date().getTime()
+    }
+    const requestSize = Object.keys(JSON.stringify(requestObj)).length; // 璇锋眰鏁版嵁澶у皬
+    const limitSize = 5 * 1024 * 1024; // 闄愬埗瀛樻斁鏁版嵁5M
+    if (requestSize >= limitSize) {
+      console.warn(`[${config.url}]: ` + '璇锋眰鏁版嵁澶у皬瓒呭嚭鍏佽鐨�5M闄愬埗锛屾棤娉曡繘琛岄槻閲嶅鎻愪氦楠岃瘉銆�')
+      return config;
+    }
+    const sessionObj = cache.session.getJSON('sessionObj')
+    if (sessionObj === undefined || sessionObj === null || sessionObj === '') {
+      cache.session.setJSON('sessionObj', requestObj)
+    } else {
+      const s_url = sessionObj.url;                  // 璇锋眰鍦板潃
+      const s_data = sessionObj.data;                // 璇锋眰鏁版嵁
+      const s_time = sessionObj.time;                // 璇锋眰鏃堕棿
+      const interval = 1000;                         // 闂撮殧鏃堕棿(ms)锛屽皬浜庢鏃堕棿瑙嗕负閲嶅鎻愪氦
+      if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
+        const message = '鏁版嵁姝e湪澶勭悊锛岃鍕块噸澶嶆彁浜�';
+        console.warn(`[${s_url}]: ` + message)
+        return Promise.reject(new Error(message))
+      } else {
+        cache.session.setJSON('sessionObj', requestObj)
+      }
+    }
+  }
+  return config
+}, error => {
+    console.log(error)
+    Promise.reject(error)
+})
+
+// 鍝嶅簲鎷︽埅鍣�
+service.interceptors.response.use(res => {
+    // 鏈缃姸鎬佺爜鍒欓粯璁ゆ垚鍔熺姸鎬�
+    const code = res.data.code || 200;
+    // 鑾峰彇閿欒淇℃伅
+    const msg = errorCode[code] || res.data.msg || errorCode['default']
+    // 浜岃繘鍒舵暟鎹垯鐩存帴杩斿洖
+    if (res.request.responseType ===  'blob' || res.request.responseType ===  'arraybuffer') {
+      return res.data
+    }
+    if (code === 401) {
+      if (!isRelogin.show) {
+        isRelogin.show = true;
+        MessageBox.confirm('鐧诲綍鐘舵�佸凡杩囨湡锛屾偍鍙互缁х画鐣欏湪璇ラ〉闈紝鎴栬�呴噸鏂扮櫥褰�', '绯荤粺鎻愮ず', { confirmButtonText: '閲嶆柊鐧诲綍', cancelButtonText: '鍙栨秷', type: 'warning' }).then(() => {
+          isRelogin.show = false;
+          store.dispatch('LogOut').then(() => {
+            location.href = '/index';
+          })
+      }).catch(() => {
+        isRelogin.show = false;
+      });
+    }
+      return Promise.reject('鏃犳晥鐨勪細璇濓紝鎴栬�呬細璇濆凡杩囨湡锛岃閲嶆柊鐧诲綍銆�')
+    } else if (code === 500) {
+      Message({ message: msg, type: 'error' })
+      return Promise.reject(new Error(msg))
+    } else if (code === 601) {
+      Message({ message: msg, type: 'warning' })
+      return Promise.reject('error')
+    } else if (code !== 200) {
+      Notification.error({ title: msg })
+      return Promise.reject('error')
+    } else {
+      return res.data
+    }
+  },
+  error => {
+    console.log('err' + error)
+    let { message } = error;
+    if (message == "Network Error") {
+      message = "鍚庣鎺ュ彛杩炴帴寮傚父";
+    } else if (message.includes("timeout")) {
+      message = "绯荤粺鎺ュ彛璇锋眰瓒呮椂";
+    } else if (message.includes("Request failed with status code")) {
+      message = "绯荤粺鎺ュ彛" + message.substr(message.length - 3) + "寮傚父";
+    }
+    Message({ message: message, type: 'error', duration: 5 * 1000 })
+    return Promise.reject(error)
+  }
+)
+
+// 閫氱敤涓嬭浇鏂规硶
+export function download(url, params, filename, config) {
+  downloadLoadingInstance = Loading.service({ text: "姝e湪涓嬭浇鏁版嵁锛岃绋嶅��", spinner: "el-icon-loading", background: "rgba(0, 0, 0, 0.7)", })
+  return service.post(url, params, {
+    transformRequest: [(params) => { return tansParams(params) }],
+    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
+    responseType: 'blob',
+    ...config
+  }).then(async (data) => {
+    const isBlob = blobValidate(data);
+    if (isBlob) {
+      const blob = new Blob([data])
+      saveAs(blob, filename)
+    } else {
+      const resText = await data.text();
+      const rspObj = JSON.parse(resText);
+      const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']
+      Message.error(errMsg);
+    }
+    downloadLoadingInstance.close();
+  }).catch((r) => {
+    console.error(r)
+    Message.error('涓嬭浇鏂囦欢鍑虹幇閿欒锛岃鑱旂郴绠$悊鍛橈紒')
+    downloadLoadingInstance.close();
+  })
+}
+
+export default service
diff --git a/jcdm-ui/src/utils/ruoyi.js b/jcdm-ui/src/utils/ruoyi.js
new file mode 100644
index 0000000..2550f42
--- /dev/null
+++ b/jcdm-ui/src/utils/ruoyi.js
@@ -0,0 +1,232 @@
+
+
+/**
+ * 閫氱敤js鏂规硶灏佽澶勭悊
+ */
+
+// 鏃ユ湡鏍煎紡鍖�
+export function parseTime(time, pattern) {
+  if (arguments.length === 0 || !time) {
+    return null
+  }
+  const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}'
+  let date
+  if (typeof time === 'object') {
+    date = time
+  } else {
+    if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
+      time = parseInt(time)
+    } else if (typeof time === 'string') {
+      time = time.replace(new RegExp(/-/gm), '/').replace('T', ' ').replace(new RegExp(/\.[\d]{3}/gm), '');
+    }
+    if ((typeof time === 'number') && (time.toString().length === 10)) {
+      time = time * 1000
+    }
+    date = new Date(time)
+  }
+  const formatObj = {
+    y: date.getFullYear(),
+    m: date.getMonth() + 1,
+    d: date.getDate(),
+    h: date.getHours(),
+    i: date.getMinutes(),
+    s: date.getSeconds(),
+    a: date.getDay()
+  }
+  const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
+    let value = formatObj[key]
+    // Note: getDay() returns 0 on Sunday
+    if (key === 'a') { return ['鏃�', '涓�', '浜�', '涓�', '鍥�', '浜�', '鍏�'][value] }
+    if (result.length > 0 && value < 10) {
+      value = '0' + value
+    }
+    return value || 0
+  })
+  return time_str
+}
+
+// 琛ㄥ崟閲嶇疆
+export function resetForm(refName) {
+  if (this.$refs[refName]) {
+    this.$refs[refName].resetFields();
+  }
+}
+
+// 娣诲姞鏃ユ湡鑼冨洿
+export function addDateRange(params, dateRange, propName) {
+  let search = params;
+  search.params = typeof (search.params) === 'object' && search.params !== null && !Array.isArray(search.params) ? search.params : {};
+  dateRange = Array.isArray(dateRange) ? dateRange : [];
+  if (typeof (propName) === 'undefined') {
+    search.params['beginTime'] = dateRange[0];
+    search.params['endTime'] = dateRange[1];
+  } else {
+    search.params['begin' + propName] = dateRange[0];
+    search.params['end' + propName] = dateRange[1];
+  }
+  return search;
+}
+
+// 鍥炴樉鏁版嵁瀛楀吀
+export function selectDictLabel(datas, value) {
+  if (value === undefined) {
+    return "";
+  }
+  var actions = [];
+  Object.keys(datas).some((key) => {
+    if (datas[key].value == ('' + value)) {
+      actions.push(datas[key].label);
+      return true;
+    }
+  })
+  if (actions.length === 0) {
+    actions.push(value);
+  }
+  return actions.join('');
+}
+
+// 鍥炴樉鏁版嵁瀛楀吀锛堝瓧绗︿覆銆佹暟缁勶級
+export function selectDictLabels(datas, value, separator) {
+  if (value === undefined || value.length ===0) {
+    return "";
+  }
+  if (Array.isArray(value)) {
+    value = value.join(",");
+  }
+  var actions = [];
+  var currentSeparator = undefined === separator ? "," : separator;
+  var temp = value.split(currentSeparator);
+  Object.keys(value.split(currentSeparator)).some((val) => {
+    var match = false;
+    Object.keys(datas).some((key) => {
+      if (datas[key].value == ('' + temp[val])) {
+        actions.push(datas[key].label + currentSeparator);
+        match = true;
+      }
+    })
+    if (!match) {
+      actions.push(temp[val] + currentSeparator);
+    }
+  })
+  return actions.join('').substring(0, actions.join('').length - 1);
+}
+
+// 瀛楃涓叉牸寮忓寲(%s )
+export function sprintf(str) {
+  var args = arguments, flag = true, i = 1;
+  str = str.replace(/%s/g, function () {
+    var arg = args[i++];
+    if (typeof arg === 'undefined') {
+      flag = false;
+      return '';
+    }
+    return arg;
+  });
+  return flag ? str : '';
+}
+
+// 杞崲瀛楃涓诧紝undefined,null绛夎浆鍖栦负""
+export function parseStrEmpty(str) {
+  if (!str || str == "undefined" || str == "null") {
+    return "";
+  }
+  return str;
+}
+
+// 鏁版嵁鍚堝苟
+export function mergeRecursive(source, target) {
+  for (var p in target) {
+    try {
+      if (target[p].constructor == Object) {
+        source[p] = mergeRecursive(source[p], target[p]);
+      } else {
+        source[p] = target[p];
+      }
+    } catch (e) {
+      source[p] = target[p];
+    }
+  }
+  return source;
+};
+
+/**
+ * 鏋勯�犳爲鍨嬬粨鏋勬暟鎹�
+ * @param {*} data 鏁版嵁婧�
+ * @param {*} id id瀛楁 榛樿 'id'
+ * @param {*} parentId 鐖惰妭鐐瑰瓧娈� 榛樿 'parentId'
+ * @param {*} children 瀛╁瓙鑺傜偣瀛楁 榛樿 'children'
+ */
+export function handleTree(data, id, parentId, children) {
+  let config = {
+    id: id || 'id',
+    parentId: parentId || 'parentId',
+    childrenList: children || 'children'
+  };
+
+  var childrenListMap = {};
+  var nodeIds = {};
+  var tree = [];
+
+  for (let d of data) {
+    let parentId = d[config.parentId];
+    if (childrenListMap[parentId] == null) {
+      childrenListMap[parentId] = [];
+    }
+    nodeIds[d[config.id]] = d;
+    childrenListMap[parentId].push(d);
+  }
+
+  for (let d of data) {
+    let parentId = d[config.parentId];
+    if (nodeIds[parentId] == null) {
+      tree.push(d);
+    }
+  }
+
+  for (let t of tree) {
+    adaptToChildrenList(t);
+  }
+
+  function adaptToChildrenList(o) {
+    if (childrenListMap[o[config.id]] !== null) {
+      o[config.childrenList] = childrenListMap[o[config.id]];
+    }
+    if (o[config.childrenList]) {
+      for (let c of o[config.childrenList]) {
+        adaptToChildrenList(c);
+      }
+    }
+  }
+  return tree;
+}
+
+/**
+* 鍙傛暟澶勭悊
+* @param {*} params  鍙傛暟
+*/
+export function tansParams(params) {
+  let result = ''
+  for (const propName of Object.keys(params)) {
+    const value = params[propName];
+    var part = encodeURIComponent(propName) + "=";
+    if (value !== null && value !== "" && typeof (value) !== "undefined") {
+      if (typeof value === 'object') {
+        for (const key of Object.keys(value)) {
+          if (value[key] !== null && value[key] !== "" && typeof (value[key]) !== 'undefined') {
+            let params = propName + '[' + key + ']';
+            var subPart = encodeURIComponent(params) + "=";
+            result += subPart + encodeURIComponent(value[key]) + "&";
+          }
+        }
+      } else {
+        result += part + encodeURIComponent(value) + "&";
+      }
+    }
+  }
+  return result
+}
+
+// 楠岃瘉鏄惁涓篵lob鏍煎紡
+export function blobValidate(data) {
+  return data.type !== 'application/json'
+}
diff --git a/jcdm-ui/src/utils/scroll-to.js b/jcdm-ui/src/utils/scroll-to.js
new file mode 100644
index 0000000..c5d8e04
--- /dev/null
+++ b/jcdm-ui/src/utils/scroll-to.js
@@ -0,0 +1,58 @@
+Math.easeInOutQuad = function(t, b, c, d) {
+  t /= d / 2
+  if (t < 1) {
+    return c / 2 * t * t + b
+  }
+  t--
+  return -c / 2 * (t * (t - 2) - 1) + b
+}
+
+// requestAnimationFrame for Smart Animating http://goo.gl/sx5sts
+var requestAnimFrame = (function() {
+  return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) { window.setTimeout(callback, 1000 / 60) }
+})()
+
+/**
+ * Because it's so fucking difficult to detect the scrolling element, just move them all
+ * @param {number} amount
+ */
+function move(amount) {
+  document.documentElement.scrollTop = amount
+  document.body.parentNode.scrollTop = amount
+  document.body.scrollTop = amount
+}
+
+function position() {
+  return document.documentElement.scrollTop || document.body.parentNode.scrollTop || document.body.scrollTop
+}
+
+/**
+ * @param {number} to
+ * @param {number} duration
+ * @param {Function} callback
+ */
+export function scrollTo(to, duration, callback) {
+  const start = position()
+  const change = to - start
+  const increment = 20
+  let currentTime = 0
+  duration = (typeof (duration) === 'undefined') ? 500 : duration
+  var animateScroll = function() {
+    // increment the time
+    currentTime += increment
+    // find the value with the quadratic in-out easing function
+    var val = Math.easeInOutQuad(currentTime, start, change, duration)
+    // move the document.body
+    move(val)
+    // do the animation unless its over
+    if (currentTime < duration) {
+      requestAnimFrame(animateScroll)
+    } else {
+      if (callback && typeof (callback) === 'function') {
+        // the animation is done so lets callback
+        callback()
+      }
+    }
+  }
+  animateScroll()
+}
diff --git a/jcdm-ui/src/utils/validate.js b/jcdm-ui/src/utils/validate.js
new file mode 100644
index 0000000..57a568e
--- /dev/null
+++ b/jcdm-ui/src/utils/validate.js
@@ -0,0 +1,80 @@
+/**
+ * @param {string} path
+ * @returns {Boolean}
+ */
+export function isExternal(path) {
+  return /^(https?:|mailto:|tel:)/.test(path)
+}
+
+/**
+ * @param {string} str
+ * @returns {Boolean}
+ */
+export function validUsername(str) {
+  const valid_map = ['admin', 'editor']
+  return valid_map.indexOf(str.trim()) >= 0
+}
+
+/**
+ * @param {string} url
+ * @returns {Boolean}
+ */
+export function validURL(url) {
+  const reg = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/
+  return reg.test(url)
+}
+
+/**
+ * @param {string} str
+ * @returns {Boolean}
+ */
+export function validLowerCase(str) {
+  const reg = /^[a-z]+$/
+  return reg.test(str)
+}
+
+/**
+ * @param {string} str
+ * @returns {Boolean}
+ */
+export function validUpperCase(str) {
+  const reg = /^[A-Z]+$/
+  return reg.test(str)
+}
+
+/**
+ * @param {string} str
+ * @returns {Boolean}
+ */
+export function validAlphabets(str) {
+  const reg = /^[A-Za-z]+$/
+  return reg.test(str)
+}
+
+/**
+ * @param {string} email
+ * @returns {Boolean}
+ */
+export function validEmail(email) {
+  const reg = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
+  return reg.test(email)
+}
+
+/**
+ * @param {string} str
+ * @returns {Boolean}
+ */
+export function isString(str) {
+  return typeof str === 'string' || str instanceof String;
+}
+
+/**
+ * @param {Array} arg
+ * @returns {Boolean}
+ */
+export function isArray(arg) {
+  if (typeof Array.isArray === 'undefined') {
+    return Object.prototype.toString.call(arg) === '[object Array]'
+  }
+  return Array.isArray(arg)
+}
diff --git a/jcdm-ui/src/views/components/icons/element-icons.js b/jcdm-ui/src/views/components/icons/element-icons.js
new file mode 100644
index 0000000..9ea4d63
--- /dev/null
+++ b/jcdm-ui/src/views/components/icons/element-icons.js
@@ -0,0 +1,3 @@
+const elementIcons = ['platform-eleme', 'eleme', 'delete-solid', 'delete', 's-tools', 'setting', 'user-solid', 'user', 'phone', 'phone-outline', 'more', 'more-outline', 'star-on', 'star-off', 's-goods', 'goods', 'warning', 'warning-outline', 'question', 'info', 'remove', 'circle-plus', 'success', 'error', 'zoom-in', 'zoom-out', 'remove-outline', 'circle-plus-outline', 'circle-check', 'circle-close', 's-help', 'help', 'minus', 'plus', 'check', 'close', 'picture', 'picture-outline', 'picture-outline-round', 'upload', 'upload2', 'download', 'camera-solid', 'camera', 'video-camera-solid', 'video-camera', 'message-solid', 'bell', 's-cooperation', 's-order', 's-platform', 's-fold', 's-unfold', 's-operation', 's-promotion', 's-home', 's-release', 's-ticket', 's-management', 's-open', 's-shop', 's-marketing', 's-flag', 's-comment', 's-finance', 's-claim', 's-custom', 's-opportunity', 's-data', 's-check', 's-grid', 'menu', 'share', 'd-caret', 'caret-left', 'caret-right', 'caret-bottom', 'caret-top', 'bottom-left', 'bottom-right', 'back', 'right', 'bottom', 'top', 'top-left', 'top-right', 'arrow-left', 'arrow-right', 'arrow-down', 'arrow-up', 'd-arrow-left', 'd-arrow-right', 'video-pause', 'video-play', 'refresh', 'refresh-right', 'refresh-left', 'finished', 'sort', 'sort-up', 'sort-down', 'rank', 'loading', 'view', 'c-scale-to-original', 'date', 'edit', 'edit-outline', 'folder', 'folder-opened', 'folder-add', 'folder-remove', 'folder-delete', 'folder-checked', 'tickets', 'document-remove', 'document-delete', 'document-copy', 'document-checked', 'document', 'document-add', 'printer', 'paperclip', 'takeaway-box', 'search', 'monitor', 'attract', 'mobile', 'scissors', 'umbrella', 'headset', 'brush', 'mouse', 'coordinate', 'magic-stick', 'reading', 'data-line', 'data-board', 'pie-chart', 'data-analysis', 'collection-tag', 'film', 'suitcase', 'suitcase-1', 'receiving', 'collection', 'files', 'notebook-1', 'notebook-2', 'toilet-paper', 'office-building', 'school', 'table-lamp', 'house', 'no-smoking', 'smoking', 'shopping-cart-full', 'shopping-cart-1', 'shopping-cart-2', 'shopping-bag-1', 'shopping-bag-2', 'sold-out', 'sell', 'present', 'box', 'bank-card', 'money', 'coin', 'wallet', 'discount', 'price-tag', 'news', 'guide', 'male', 'female', 'thumb', 'cpu', 'link', 'connection', 'open', 'turn-off', 'set-up', 'chat-round', 'chat-line-round', 'chat-square', 'chat-dot-round', 'chat-dot-square', 'chat-line-square', 'message', 'postcard', 'position', 'turn-off-microphone', 'microphone', 'close-notification', 'bangzhu', 'time', 'odometer', 'crop', 'aim', 'switch-button', 'full-screen', 'copy-document', 'mic', 'stopwatch', 'medal-1', 'medal', 'trophy', 'trophy-1', 'first-aid-kit', 'discover', 'place', 'location', 'location-outline', 'location-information', 'add-location', 'delete-location', 'map-location', 'alarm-clock', 'timer', 'watch-1', 'watch', 'lock', 'unlock', 'key', 'service', 'mobile-phone', 'bicycle', 'truck', 'ship', 'basketball', 'football', 'soccer', 'baseball', 'wind-power', 'light-rain', 'lightning', 'heavy-rain', 'sunrise', 'sunrise-1', 'sunset', 'sunny', 'cloudy', 'partly-cloudy', 'cloudy-and-sunny', 'moon', 'moon-night', 'dish', 'dish-1', 'food', 'chicken', 'fork-spoon', 'knife-fork', 'burger', 'tableware', 'sugar', 'dessert', 'ice-cream', 'hot-water', 'water-cup', 'coffee-cup', 'cold-drink', 'goblet', 'goblet-full', 'goblet-square', 'goblet-square-full', 'refrigerator', 'grape', 'watermelon', 'cherry', 'apple', 'pear', 'orange', 'coffee', 'ice-tea', 'ice-drink', 'milk-tea', 'potato-strips', 'lollipop', 'ice-cream-square', 'ice-cream-round']
+
+export default elementIcons
diff --git a/jcdm-ui/src/views/components/icons/index.vue b/jcdm-ui/src/views/components/icons/index.vue
new file mode 100644
index 0000000..d3c9a71
--- /dev/null
+++ b/jcdm-ui/src/views/components/icons/index.vue
@@ -0,0 +1,87 @@
+<template>
+  <div class="icons-container">
+    <aside>
+      <a href="#" target="_blank">Add and use
+      </a>
+    </aside>
+    <el-tabs type="border-card">
+      <el-tab-pane label="Icons">
+        <div v-for="item of svgIcons" :key="item">
+          <el-tooltip placement="top">
+            <div slot="content">
+              {{ generateIconCode(item) }}
+            </div>
+            <div class="icon-item">
+              <svg-icon :icon-class="item" class-name="disabled" />
+              <span>{{ item }}</span>
+            </div>
+          </el-tooltip>
+        </div>
+      </el-tab-pane>
+      <el-tab-pane label="Element-UI Icons">
+        <div v-for="item of elementIcons" :key="item">
+          <el-tooltip placement="top">
+            <div slot="content">
+              {{ generateElementIconCode(item) }}
+            </div>
+            <div class="icon-item">
+              <i :class="'el-icon-' + item" />
+              <span>{{ item }}</span>
+            </div>
+          </el-tooltip>
+        </div>
+      </el-tab-pane>
+    </el-tabs>
+  </div>
+</template>
+
+<script>
+import svgIcons from './svg-icons'
+import elementIcons from './element-icons'
+
+export default {
+  name: 'Icons',
+  data() {
+    return {
+      svgIcons,
+      elementIcons
+    }
+  },
+  methods: {
+    generateIconCode(symbol) {
+      return `<svg-icon icon-class="${symbol}" />`
+    },
+    generateElementIconCode(symbol) {
+      return `<i class="el-icon-${symbol}" />`
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.icons-container {
+  margin: 10px 20px 0;
+  overflow: hidden;
+
+  .icon-item {
+    margin: 20px;
+    height: 85px;
+    text-align: center;
+    width: 100px;
+    float: left;
+    font-size: 30px;
+    color: #24292e;
+    cursor: pointer;
+  }
+
+  span {
+    display: block;
+    font-size: 16px;
+    margin-top: 10px;
+  }
+
+  .disabled {
+    pointer-events: none;
+  }
+}
+</style>
diff --git a/jcdm-ui/src/views/components/icons/svg-icons.js b/jcdm-ui/src/views/components/icons/svg-icons.js
new file mode 100644
index 0000000..724cd8e
--- /dev/null
+++ b/jcdm-ui/src/views/components/icons/svg-icons.js
@@ -0,0 +1,10 @@
+const req = require.context('../../../assets/icons/svg', false, /\.svg$/)
+const requireAll = requireContext => requireContext.keys()
+
+const re = /\.\/(.*)\.svg/
+
+const svgIcons = requireAll(req).map(i => {
+  return i.match(re)[1]
+})
+
+export default svgIcons
diff --git a/jcdm-ui/src/views/dashboard/BarChart.vue b/jcdm-ui/src/views/dashboard/BarChart.vue
new file mode 100644
index 0000000..88e7ef6
--- /dev/null
+++ b/jcdm-ui/src/views/dashboard/BarChart.vue
@@ -0,0 +1,102 @@
+<template>
+  <div :class="className" :style="{height:height,width:width}" />
+</template>
+
+<script>
+import * as echarts from 'echarts'
+require('echarts/theme/macarons') // echarts theme
+import resize from './mixins/resize'
+
+const animationDuration = 6000
+
+export default {
+  mixins: [resize],
+  props: {
+    className: {
+      type: String,
+      default: 'chart'
+    },
+    width: {
+      type: String,
+      default: '100%'
+    },
+    height: {
+      type: String,
+      default: '300px'
+    }
+  },
+  data() {
+    return {
+      chart: null
+    }
+  },
+  mounted() {
+    this.$nextTick(() => {
+      this.initChart()
+    })
+  },
+  beforeDestroy() {
+    if (!this.chart) {
+      return
+    }
+    this.chart.dispose()
+    this.chart = null
+  },
+  methods: {
+    initChart() {
+      this.chart = echarts.init(this.$el, 'macarons')
+
+      this.chart.setOption({
+        tooltip: {
+          trigger: 'axis',
+          axisPointer: { // 鍧愭爣杞存寚绀哄櫒锛屽潗鏍囪酱瑙﹀彂鏈夋晥
+            type: 'shadow' // 榛樿涓虹洿绾匡紝鍙�変负锛�'line' | 'shadow'
+          }
+        },
+        grid: {
+          top: 10,
+          left: '2%',
+          right: '2%',
+          bottom: '3%',
+          containLabel: true
+        },
+        xAxis: [{
+          type: 'category',
+          data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
+          axisTick: {
+            alignWithLabel: true
+          }
+        }],
+        yAxis: [{
+          type: 'value',
+          axisTick: {
+            show: false
+          }
+        }],
+        series: [{
+          name: 'pageA',
+          type: 'bar',
+          stack: 'vistors',
+          barWidth: '60%',
+          data: [79, 52, 200, 334, 390, 330, 220],
+          animationDuration
+        }, {
+          name: 'pageB',
+          type: 'bar',
+          stack: 'vistors',
+          barWidth: '60%',
+          data: [80, 52, 200, 334, 390, 330, 220],
+          animationDuration
+        }, {
+          name: 'pageC',
+          type: 'bar',
+          stack: 'vistors',
+          barWidth: '60%',
+          data: [30, 52, 200, 334, 390, 330, 220],
+          animationDuration
+        }]
+      })
+    }
+  }
+}
+</script>
diff --git a/jcdm-ui/src/views/dashboard/LineChart.vue b/jcdm-ui/src/views/dashboard/LineChart.vue
new file mode 100644
index 0000000..702ff73
--- /dev/null
+++ b/jcdm-ui/src/views/dashboard/LineChart.vue
@@ -0,0 +1,135 @@
+<template>
+  <div :class="className" :style="{height:height,width:width}" />
+</template>
+
+<script>
+import * as echarts from 'echarts'
+require('echarts/theme/macarons') // echarts theme
+import resize from './mixins/resize'
+
+export default {
+  mixins: [resize],
+  props: {
+    className: {
+      type: String,
+      default: 'chart'
+    },
+    width: {
+      type: String,
+      default: '100%'
+    },
+    height: {
+      type: String,
+      default: '350px'
+    },
+    autoResize: {
+      type: Boolean,
+      default: true
+    },
+    chartData: {
+      type: Object,
+      required: true
+    }
+  },
+  data() {
+    return {
+      chart: null
+    }
+  },
+  watch: {
+    chartData: {
+      deep: true,
+      handler(val) {
+        this.setOptions(val)
+      }
+    }
+  },
+  mounted() {
+    this.$nextTick(() => {
+      this.initChart()
+    })
+  },
+  beforeDestroy() {
+    if (!this.chart) {
+      return
+    }
+    this.chart.dispose()
+    this.chart = null
+  },
+  methods: {
+    initChart() {
+      this.chart = echarts.init(this.$el, 'macarons')
+      this.setOptions(this.chartData)
+    },
+    setOptions({ expectedData, actualData } = {}) {
+      this.chart.setOption({
+        xAxis: {
+          data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
+          boundaryGap: false,
+          axisTick: {
+            show: false
+          }
+        },
+        grid: {
+          left: 10,
+          right: 10,
+          bottom: 20,
+          top: 30,
+          containLabel: true
+        },
+        tooltip: {
+          trigger: 'axis',
+          axisPointer: {
+            type: 'cross'
+          },
+          padding: [5, 10]
+        },
+        yAxis: {
+          axisTick: {
+            show: false
+          }
+        },
+        legend: {
+          data: ['expected', 'actual']
+        },
+        series: [{
+          name: 'expected', itemStyle: {
+            normal: {
+              color: '#FF005A',
+              lineStyle: {
+                color: '#FF005A',
+                width: 2
+              }
+            }
+          },
+          smooth: true,
+          type: 'line',
+          data: expectedData,
+          animationDuration: 2800,
+          animationEasing: 'cubicInOut'
+        },
+        {
+          name: 'actual',
+          smooth: true,
+          type: 'line',
+          itemStyle: {
+            normal: {
+              color: '#3888fa',
+              lineStyle: {
+                color: '#3888fa',
+                width: 2
+              },
+              areaStyle: {
+                color: '#f3f8ff'
+              }
+            }
+          },
+          data: actualData,
+          animationDuration: 2800,
+          animationEasing: 'quadraticOut'
+        }]
+      })
+    }
+  }
+}
+</script>
diff --git a/jcdm-ui/src/views/dashboard/PanelGroup.vue b/jcdm-ui/src/views/dashboard/PanelGroup.vue
new file mode 100644
index 0000000..1a1081f
--- /dev/null
+++ b/jcdm-ui/src/views/dashboard/PanelGroup.vue
@@ -0,0 +1,181 @@
+<template>
+  <el-row :gutter="40" class="panel-group">
+    <el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
+      <div class="card-panel" @click="handleSetLineChartData('newVisitis')">
+        <div class="card-panel-icon-wrapper icon-people">
+          <svg-icon icon-class="peoples" class-name="card-panel-icon" />
+        </div>
+        <div class="card-panel-description">
+          <div class="card-panel-text">
+            璁垮
+          </div>
+          <count-to :start-val="0" :end-val="102400" :duration="2600" class="card-panel-num" />
+        </div>
+      </div>
+    </el-col>
+    <el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
+      <div class="card-panel" @click="handleSetLineChartData('messages')">
+        <div class="card-panel-icon-wrapper icon-message">
+          <svg-icon icon-class="message" class-name="card-panel-icon" />
+        </div>
+        <div class="card-panel-description">
+          <div class="card-panel-text">
+            娑堟伅
+          </div>
+          <count-to :start-val="0" :end-val="81212" :duration="3000" class="card-panel-num" />
+        </div>
+      </div>
+    </el-col>
+    <el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
+      <div class="card-panel" @click="handleSetLineChartData('purchases')">
+        <div class="card-panel-icon-wrapper icon-money">
+          <svg-icon icon-class="money" class-name="card-panel-icon" />
+        </div>
+        <div class="card-panel-description">
+          <div class="card-panel-text">
+            閲戦
+          </div>
+          <count-to :start-val="0" :end-val="9280" :duration="3200" class="card-panel-num" />
+        </div>
+      </div>
+    </el-col>
+    <el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
+      <div class="card-panel" @click="handleSetLineChartData('shoppings')">
+        <div class="card-panel-icon-wrapper icon-shopping">
+          <svg-icon icon-class="shopping" class-name="card-panel-icon" />
+        </div>
+        <div class="card-panel-description">
+          <div class="card-panel-text">
+            璁㈠崟
+          </div>
+          <count-to :start-val="0" :end-val="13600" :duration="3600" class="card-panel-num" />
+        </div>
+      </div>
+    </el-col>
+  </el-row>
+</template>
+
+<script>
+import CountTo from 'vue-count-to'
+
+export default {
+  components: {
+    CountTo
+  },
+  methods: {
+    handleSetLineChartData(type) {
+      this.$emit('handleSetLineChartData', type)
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.panel-group {
+  margin-top: 18px;
+
+  .card-panel-col {
+    margin-bottom: 32px;
+  }
+
+  .card-panel {
+    height: 108px;
+    cursor: pointer;
+    font-size: 12px;
+    position: relative;
+    overflow: hidden;
+    color: #666;
+    background: #fff;
+    box-shadow: 4px 4px 40px rgba(0, 0, 0, .05);
+    border-color: rgba(0, 0, 0, .05);
+
+    &:hover {
+      .card-panel-icon-wrapper {
+        color: #fff;
+      }
+
+      .icon-people {
+        background: #40c9c6;
+      }
+
+      .icon-message {
+        background: #36a3f7;
+      }
+
+      .icon-money {
+        background: #f4516c;
+      }
+
+      .icon-shopping {
+        background: #34bfa3
+      }
+    }
+
+    .icon-people {
+      color: #40c9c6;
+    }
+
+    .icon-message {
+      color: #36a3f7;
+    }
+
+    .icon-money {
+      color: #f4516c;
+    }
+
+    .icon-shopping {
+      color: #34bfa3
+    }
+
+    .card-panel-icon-wrapper {
+      float: left;
+      margin: 14px 0 0 14px;
+      padding: 16px;
+      transition: all 0.38s ease-out;
+      border-radius: 6px;
+    }
+
+    .card-panel-icon {
+      float: left;
+      font-size: 48px;
+    }
+
+    .card-panel-description {
+      float: right;
+      font-weight: bold;
+      margin: 26px;
+      margin-left: 0px;
+
+      .card-panel-text {
+        line-height: 18px;
+        color: rgba(0, 0, 0, 0.45);
+        font-size: 16px;
+        margin-bottom: 12px;
+      }
+
+      .card-panel-num {
+        font-size: 20px;
+      }
+    }
+  }
+}
+
+@media (max-width:550px) {
+  .card-panel-description {
+    display: none;
+  }
+
+  .card-panel-icon-wrapper {
+    float: none !important;
+    width: 100%;
+    height: 100%;
+    margin: 0 !important;
+
+    .svg-icon {
+      display: block;
+      margin: 14px auto !important;
+      float: none !important;
+    }
+  }
+}
+</style>
diff --git a/jcdm-ui/src/views/dashboard/PieChart.vue b/jcdm-ui/src/views/dashboard/PieChart.vue
new file mode 100644
index 0000000..63f0d84
--- /dev/null
+++ b/jcdm-ui/src/views/dashboard/PieChart.vue
@@ -0,0 +1,79 @@
+<template>
+  <div :class="className" :style="{height:height,width:width}" />
+</template>
+
+<script>
+import * as echarts from 'echarts'
+require('echarts/theme/macarons') // echarts theme
+import resize from './mixins/resize'
+
+export default {
+  mixins: [resize],
+  props: {
+    className: {
+      type: String,
+      default: 'chart'
+    },
+    width: {
+      type: String,
+      default: '100%'
+    },
+    height: {
+      type: String,
+      default: '300px'
+    }
+  },
+  data() {
+    return {
+      chart: null
+    }
+  },
+  mounted() {
+    this.$nextTick(() => {
+      this.initChart()
+    })
+  },
+  beforeDestroy() {
+    if (!this.chart) {
+      return
+    }
+    this.chart.dispose()
+    this.chart = null
+  },
+  methods: {
+    initChart() {
+      this.chart = echarts.init(this.$el, 'macarons')
+
+      this.chart.setOption({
+        tooltip: {
+          trigger: 'item',
+          formatter: '{a} <br/>{b} : {c} ({d}%)'
+        },
+        legend: {
+          left: 'center',
+          bottom: '10',
+          data: ['Industries', 'Technology', 'Forex', 'Gold', 'Forecasts']
+        },
+        series: [
+          {
+            name: 'WEEKLY WRITE ARTICLES',
+            type: 'pie',
+            roseType: 'radius',
+            radius: [15, 95],
+            center: ['50%', '38%'],
+            data: [
+              { value: 320, name: 'Industries' },
+              { value: 240, name: 'Technology' },
+              { value: 149, name: 'Forex' },
+              { value: 100, name: 'Gold' },
+              { value: 59, name: 'Forecasts' }
+            ],
+            animationEasing: 'cubicInOut',
+            animationDuration: 2600
+          }
+        ]
+      })
+    }
+  }
+}
+</script>
diff --git a/jcdm-ui/src/views/dashboard/RaddarChart.vue b/jcdm-ui/src/views/dashboard/RaddarChart.vue
new file mode 100644
index 0000000..312e018
--- /dev/null
+++ b/jcdm-ui/src/views/dashboard/RaddarChart.vue
@@ -0,0 +1,116 @@
+<template>
+  <div :class="className" :style="{height:height,width:width}" />
+</template>
+
+<script>
+import * as echarts from 'echarts'
+require('echarts/theme/macarons') // echarts theme
+import resize from './mixins/resize'
+
+const animationDuration = 3000
+
+export default {
+  mixins: [resize],
+  props: {
+    className: {
+      type: String,
+      default: 'chart'
+    },
+    width: {
+      type: String,
+      default: '100%'
+    },
+    height: {
+      type: String,
+      default: '300px'
+    }
+  },
+  data() {
+    return {
+      chart: null
+    }
+  },
+  mounted() {
+    this.$nextTick(() => {
+      this.initChart()
+    })
+  },
+  beforeDestroy() {
+    if (!this.chart) {
+      return
+    }
+    this.chart.dispose()
+    this.chart = null
+  },
+  methods: {
+    initChart() {
+      this.chart = echarts.init(this.$el, 'macarons')
+
+      this.chart.setOption({
+        tooltip: {
+          trigger: 'axis',
+          axisPointer: { // 鍧愭爣杞存寚绀哄櫒锛屽潗鏍囪酱瑙﹀彂鏈夋晥
+            type: 'shadow' // 榛樿涓虹洿绾匡紝鍙�変负锛�'line' | 'shadow'
+          }
+        },
+        radar: {
+          radius: '66%',
+          center: ['50%', '42%'],
+          splitNumber: 8,
+          splitArea: {
+            areaStyle: {
+              color: 'rgba(127,95,132,.3)',
+              opacity: 1,
+              shadowBlur: 45,
+              shadowColor: 'rgba(0,0,0,.5)',
+              shadowOffsetX: 0,
+              shadowOffsetY: 15
+            }
+          },
+          indicator: [
+            { name: 'Sales', max: 10000 },
+            { name: 'Administration', max: 20000 },
+            { name: 'Information Techology', max: 20000 },
+            { name: 'Customer Support', max: 20000 },
+            { name: 'Development', max: 20000 },
+            { name: 'Marketing', max: 20000 }
+          ]
+        },
+        legend: {
+          left: 'center',
+          bottom: '10',
+          data: ['Allocated Budget', 'Expected Spending', 'Actual Spending']
+        },
+        series: [{
+          type: 'radar',
+          symbolSize: 0,
+          areaStyle: {
+            normal: {
+              shadowBlur: 13,
+              shadowColor: 'rgba(0,0,0,.2)',
+              shadowOffsetX: 0,
+              shadowOffsetY: 10,
+              opacity: 1
+            }
+          },
+          data: [
+            {
+              value: [5000, 7000, 12000, 11000, 15000, 14000],
+              name: 'Allocated Budget'
+            },
+            {
+              value: [4000, 9000, 15000, 15000, 13000, 11000],
+              name: 'Expected Spending'
+            },
+            {
+              value: [5500, 11000, 12000, 15000, 12000, 12000],
+              name: 'Actual Spending'
+            }
+          ],
+          animationDuration: animationDuration
+        }]
+      })
+    }
+  }
+}
+</script>
diff --git a/jcdm-ui/src/views/dashboard/mixins/resize.js b/jcdm-ui/src/views/dashboard/mixins/resize.js
new file mode 100644
index 0000000..b1e76e9
--- /dev/null
+++ b/jcdm-ui/src/views/dashboard/mixins/resize.js
@@ -0,0 +1,56 @@
+import { debounce } from '@/utils'
+
+export default {
+  data() {
+    return {
+      $_sidebarElm: null,
+      $_resizeHandler: null
+    }
+  },
+  mounted() {
+    this.initListener()
+  },
+  activated() {
+    if (!this.$_resizeHandler) {
+      // avoid duplication init
+      this.initListener()
+    }
+
+    // when keep-alive chart activated, auto resize
+    this.resize()
+  },
+  beforeDestroy() {
+    this.destroyListener()
+  },
+  deactivated() {
+    this.destroyListener()
+  },
+  methods: {
+    // use $_ for mixins properties
+    // https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential
+    $_sidebarResizeHandler(e) {
+      if (e.propertyName === 'width') {
+        this.$_resizeHandler()
+      }
+    },
+    initListener() {
+      this.$_resizeHandler = debounce(() => {
+        this.resize()
+      }, 100)
+      window.addEventListener('resize', this.$_resizeHandler)
+
+      this.$_sidebarElm = document.getElementsByClassName('sidebar-container')[0]
+      this.$_sidebarElm && this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler)
+    },
+    destroyListener() {
+      window.removeEventListener('resize', this.$_resizeHandler)
+      this.$_resizeHandler = null
+
+      this.$_sidebarElm && this.$_sidebarElm.removeEventListener('transitionend', this.$_sidebarResizeHandler)
+    },
+    resize() {
+      const { chart } = this
+      chart && chart.resize()
+    }
+  }
+}
diff --git a/jcdm-ui/src/views/error/401.vue b/jcdm-ui/src/views/error/401.vue
new file mode 100644
index 0000000..448b6ec
--- /dev/null
+++ b/jcdm-ui/src/views/error/401.vue
@@ -0,0 +1,88 @@
+<template>
+  <div class="errPage-container">
+    <el-button icon="arrow-left" class="pan-back-btn" @click="back">
+      杩斿洖
+    </el-button>
+    <el-row>
+      <el-col :span="12">
+        <h1 class="text-jumbo text-ginormous">
+          401閿欒!
+        </h1>
+        <h2>鎮ㄦ病鏈夎闂潈闄愶紒</h2>
+        <h6>瀵逛笉璧凤紝鎮ㄦ病鏈夎闂潈闄愶紝璇蜂笉瑕佽繘琛岄潪娉曟搷浣滐紒鎮ㄥ彲浠ヨ繑鍥炰富椤甸潰</h6>
+        <ul class="list-unstyled">
+          <li class="link-type">
+            <router-link to="/">
+              鍥為椤�
+            </router-link>
+          </li>
+        </ul>
+      </el-col>
+      <el-col :span="12">
+        <img :src="errGif" width="313" height="428" alt="Girl has dropped her ice cream.">
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import errGif from '@/assets/401_images/401.gif'
+
+export default {
+  name: 'Page401',
+  data() {
+    return {
+      errGif: errGif + '?' + +new Date()
+    }
+  },
+  methods: {
+    back() {
+      if (this.$route.query.noGoBack) {
+        this.$router.push({ path: '/' })
+      } else {
+        this.$router.go(-1)
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+  .errPage-container {
+    width: 800px;
+    max-width: 100%;
+    margin: 100px auto;
+    .pan-back-btn {
+      background: #008489;
+      color: #fff;
+      border: none!important;
+    }
+    .pan-gif {
+      margin: 0 auto;
+      display: block;
+    }
+    .pan-img {
+      display: block;
+      margin: 0 auto;
+      width: 100%;
+    }
+    .text-jumbo {
+      font-size: 60px;
+      font-weight: 700;
+      color: #484848;
+    }
+    .list-unstyled {
+      font-size: 14px;
+      li {
+        padding-bottom: 5px;
+      }
+      a {
+        color: #008489;
+        text-decoration: none;
+        &:hover {
+          text-decoration: underline;
+        }
+      }
+    }
+  }
+</style>
diff --git a/jcdm-ui/src/views/error/404.vue b/jcdm-ui/src/views/error/404.vue
new file mode 100644
index 0000000..96f075c
--- /dev/null
+++ b/jcdm-ui/src/views/error/404.vue
@@ -0,0 +1,233 @@
+<template>
+  <div class="wscn-http404-container">
+    <div class="wscn-http404">
+      <div class="pic-404">
+        <img class="pic-404__parent" src="@/assets/404_images/404.png" alt="404">
+        <img class="pic-404__child left" src="@/assets/404_images/404_cloud.png" alt="404">
+        <img class="pic-404__child mid" src="@/assets/404_images/404_cloud.png" alt="404">
+        <img class="pic-404__child right" src="@/assets/404_images/404_cloud.png" alt="404">
+      </div>
+      <div class="bullshit">
+        <div class="bullshit__oops">
+          404閿欒!
+        </div>
+        <div class="bullshit__headline">
+          {{ message }}
+        </div>
+        <div class="bullshit__info">
+          瀵逛笉璧凤紝鎮ㄦ鍦ㄥ鎵剧殑椤甸潰涓嶅瓨鍦ㄣ�傚皾璇曟鏌RL鐨勯敊璇紝鐒跺悗鎸夋祻瑙堝櫒涓婄殑鍒锋柊鎸夐挳鎴栧皾璇曞湪鎴戜滑鐨勫簲鐢ㄧ▼搴忎腑鎵惧埌鍏朵粬鍐呭銆�
+        </div>
+        <router-link to="/" class="bullshit__return-home">
+          杩斿洖棣栭〉
+        </router-link>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+
+export default {
+  name: 'Page404',
+  computed: {
+    message() {
+      return '鎵句笉鍒扮綉椤碉紒'
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.wscn-http404-container{
+  transform: translate(-50%,-50%);
+  position: absolute;
+  top: 40%;
+  left: 50%;
+}
+.wscn-http404 {
+  position: relative;
+  width: 1200px;
+  padding: 0 50px;
+  overflow: hidden;
+  .pic-404 {
+    position: relative;
+    float: left;
+    width: 600px;
+    overflow: hidden;
+    &__parent {
+      width: 100%;
+    }
+    &__child {
+      position: absolute;
+      &.left {
+        width: 80px;
+        top: 17px;
+        left: 220px;
+        opacity: 0;
+        animation-name: cloudLeft;
+        animation-duration: 2s;
+        animation-timing-function: linear;
+        animation-fill-mode: forwards;
+        animation-delay: 1s;
+      }
+      &.mid {
+        width: 46px;
+        top: 10px;
+        left: 420px;
+        opacity: 0;
+        animation-name: cloudMid;
+        animation-duration: 2s;
+        animation-timing-function: linear;
+        animation-fill-mode: forwards;
+        animation-delay: 1.2s;
+      }
+      &.right {
+        width: 62px;
+        top: 100px;
+        left: 500px;
+        opacity: 0;
+        animation-name: cloudRight;
+        animation-duration: 2s;
+        animation-timing-function: linear;
+        animation-fill-mode: forwards;
+        animation-delay: 1s;
+      }
+      @keyframes cloudLeft {
+        0% {
+          top: 17px;
+          left: 220px;
+          opacity: 0;
+        }
+        20% {
+          top: 33px;
+          left: 188px;
+          opacity: 1;
+        }
+        80% {
+          top: 81px;
+          left: 92px;
+          opacity: 1;
+        }
+        100% {
+          top: 97px;
+          left: 60px;
+          opacity: 0;
+        }
+      }
+      @keyframes cloudMid {
+        0% {
+          top: 10px;
+          left: 420px;
+          opacity: 0;
+        }
+        20% {
+          top: 40px;
+          left: 360px;
+          opacity: 1;
+        }
+        70% {
+          top: 130px;
+          left: 180px;
+          opacity: 1;
+        }
+        100% {
+          top: 160px;
+          left: 120px;
+          opacity: 0;
+        }
+      }
+      @keyframes cloudRight {
+        0% {
+          top: 100px;
+          left: 500px;
+          opacity: 0;
+        }
+        20% {
+          top: 120px;
+          left: 460px;
+          opacity: 1;
+        }
+        80% {
+          top: 180px;
+          left: 340px;
+          opacity: 1;
+        }
+        100% {
+          top: 200px;
+          left: 300px;
+          opacity: 0;
+        }
+      }
+    }
+  }
+  .bullshit {
+    position: relative;
+    float: left;
+    width: 300px;
+    padding: 30px 0;
+    overflow: hidden;
+    &__oops {
+      font-size: 32px;
+      font-weight: bold;
+      line-height: 40px;
+      color: #1482f0;
+      opacity: 0;
+      margin-bottom: 20px;
+      animation-name: slideUp;
+      animation-duration: 0.5s;
+      animation-fill-mode: forwards;
+    }
+    &__headline {
+      font-size: 20px;
+      line-height: 24px;
+      color: #222;
+      font-weight: bold;
+      opacity: 0;
+      margin-bottom: 10px;
+      animation-name: slideUp;
+      animation-duration: 0.5s;
+      animation-delay: 0.1s;
+      animation-fill-mode: forwards;
+    }
+    &__info {
+      font-size: 13px;
+      line-height: 21px;
+      color: grey;
+      opacity: 0;
+      margin-bottom: 30px;
+      animation-name: slideUp;
+      animation-duration: 0.5s;
+      animation-delay: 0.2s;
+      animation-fill-mode: forwards;
+    }
+    &__return-home {
+      display: block;
+      float: left;
+      width: 110px;
+      height: 36px;
+      background: #1482f0;
+      border-radius: 100px;
+      text-align: center;
+      color: #ffffff;
+      opacity: 0;
+      font-size: 14px;
+      line-height: 36px;
+      cursor: pointer;
+      animation-name: slideUp;
+      animation-duration: 0.5s;
+      animation-delay: 0.3s;
+      animation-fill-mode: forwards;
+    }
+    @keyframes slideUp {
+      0% {
+        transform: translateY(60px);
+        opacity: 0;
+      }
+      100% {
+        transform: translateY(0);
+        opacity: 1;
+      }
+    }
+  }
+}
+</style>
diff --git a/jcdm-ui/src/views/index.vue b/jcdm-ui/src/views/index.vue
new file mode 100644
index 0000000..d382cd8
--- /dev/null
+++ b/jcdm-ui/src/views/index.vue
@@ -0,0 +1,96 @@
+<template>
+  <div class="app-container home">
+    <el-row :gutter="20">
+      <el-col :sm="24" :lg="24">
+        <blockquote class="text-warning" style="font-size: 14px">
+          姹熷MES绠$悊绯荤粺
+        </blockquote>
+
+        <hr />
+      </el-col>
+    </el-row>
+
+  </div>
+</template>
+
+<script>
+export default {
+  name: "Index",
+  data() {
+    return {
+      // 鐗堟湰鍙�
+      version: "3.8.6"
+    };
+  },
+  methods: {
+    goTarget(href) {
+      window.open(href, "_blank");
+    }
+  }
+};
+</script>
+
+<style scoped lang="scss">
+.home {
+  blockquote {
+    padding: 10px 20px;
+    margin: 0 0 20px;
+    font-size: 17.5px;
+    border-left: 5px solid #eee;
+  }
+  hr {
+    margin-top: 20px;
+    margin-bottom: 20px;
+    border: 0;
+    border-top: 1px solid #eee;
+  }
+  .col-item {
+    margin-bottom: 20px;
+  }
+
+  ul {
+    padding: 0;
+    margin: 0;
+  }
+
+  font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
+  font-size: 13px;
+  color: #676a6c;
+  overflow-x: hidden;
+
+  ul {
+    list-style-type: none;
+  }
+
+  h4 {
+    margin-top: 0px;
+  }
+
+  h2 {
+    margin-top: 10px;
+    font-size: 26px;
+    font-weight: 100;
+  }
+
+  p {
+    margin-top: 10px;
+
+    b {
+      font-weight: 700;
+    }
+  }
+
+  .update-log {
+    ol {
+      display: block;
+      list-style-type: decimal;
+      margin-block-start: 1em;
+      margin-block-end: 1em;
+      margin-inline-start: 0;
+      margin-inline-end: 0;
+      padding-inline-start: 40px;
+    }
+  }
+}
+</style>
+
diff --git a/jcdm-ui/src/views/index_v1.vue b/jcdm-ui/src/views/index_v1.vue
new file mode 100644
index 0000000..d2d2ec6
--- /dev/null
+++ b/jcdm-ui/src/views/index_v1.vue
@@ -0,0 +1,98 @@
+<template>
+  <div class="dashboard-editor-container">
+
+    <panel-group @handleSetLineChartData="handleSetLineChartData" />
+
+    <el-row style="background:#fff;padding:16px 16px 0;margin-bottom:32px;">
+      <line-chart :chart-data="lineChartData" />
+    </el-row>
+
+    <el-row :gutter="32">
+      <el-col :xs="24" :sm="24" :lg="8">
+        <div class="chart-wrapper">
+          <raddar-chart />
+        </div>
+      </el-col>
+      <el-col :xs="24" :sm="24" :lg="8">
+        <div class="chart-wrapper">
+          <pie-chart />
+        </div>
+      </el-col>
+      <el-col :xs="24" :sm="24" :lg="8">
+        <div class="chart-wrapper">
+          <bar-chart />
+        </div>
+      </el-col>
+    </el-row>
+
+    
+  </div>
+</template>
+
+<script>
+import PanelGroup from './dashboard/PanelGroup'
+import LineChart from './dashboard/LineChart'
+import RaddarChart from './dashboard/RaddarChart'
+import PieChart from './dashboard/PieChart'
+import BarChart from './dashboard/BarChart'
+
+const lineChartData = {
+  newVisitis: {
+    expectedData: [100, 120, 161, 134, 105, 160, 165],
+    actualData: [120, 82, 91, 154, 162, 140, 145]
+  },
+  messages: {
+    expectedData: [200, 192, 120, 144, 160, 130, 140],
+    actualData: [180, 160, 151, 106, 145, 150, 130]
+  },
+  purchases: {
+    expectedData: [80, 100, 121, 104, 105, 90, 100],
+    actualData: [120, 90, 100, 138, 142, 130, 130]
+  },
+  shoppings: {
+    expectedData: [130, 140, 141, 142, 145, 150, 160],
+    actualData: [120, 82, 91, 154, 162, 140, 130]
+  }
+}
+
+export default {
+  name: 'Index',
+  components: {
+    PanelGroup,
+    LineChart,
+    RaddarChart,
+    PieChart,
+    BarChart
+  },
+  data() {
+    return {
+      lineChartData: lineChartData.newVisitis
+    }
+  },
+  methods: {
+    handleSetLineChartData(type) {
+      this.lineChartData = lineChartData[type]
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.dashboard-editor-container {
+  padding: 32px;
+  background-color: rgb(240, 242, 245);
+  position: relative;
+
+  .chart-wrapper {
+    background: #fff;
+    padding: 16px 16px 0;
+    margin-bottom: 32px;
+  }
+}
+
+@media (max-width:1024px) {
+  .chart-wrapper {
+    padding: 8px;
+  }
+}
+</style>
diff --git a/jcdm-ui/src/views/login.vue b/jcdm-ui/src/views/login.vue
new file mode 100644
index 0000000..bb9ea3c
--- /dev/null
+++ b/jcdm-ui/src/views/login.vue
@@ -0,0 +1,244 @@
+<template>
+  <div class="login">
+    <div class="login-left">
+
+    </div>
+    <div class="login-right">
+      <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form">
+        <h2 class="title">姹熷MES绯荤粺</h2>
+        <el-form-item prop="username">
+          <el-input
+            v-model="loginForm.username"
+            type="text"
+            auto-complete="off"
+            placeholder="璐﹀彿"
+          >
+            <svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon" />
+          </el-input>
+        </el-form-item>
+        <el-form-item prop="password">
+          <el-input
+            v-model="loginForm.password"
+            type="password"
+            auto-complete="off"
+            placeholder="瀵嗙爜"
+            @keyup.enter.native="handleLogin"
+          >
+            <svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon" />
+          </el-input>
+        </el-form-item>
+<!--        <el-form-item prop="code" v-if="captchaEnabled">
+          <el-input
+            v-model="loginForm.code"
+            auto-complete="off"
+            placeholder="楠岃瘉鐮�"
+            style="width: 63%"
+            @keyup.enter.native="handleLogin"
+          >
+            <svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon" />
+          </el-input>
+          <div class="login-code">
+            <img :src="codeUrl" @click="getCode" class="login-code-img"/>
+          </div>
+        </el-form-item>-->
+        <el-checkbox v-model="loginForm.rememberMe" style="margin:0px 0px 25px 0px;">璁颁綇瀵嗙爜</el-checkbox>
+        <el-form-item style="width:100%;">
+          <el-button
+            :loading="loading"
+            size="medium"
+            type="primary"
+            style="width:100%;"
+            @click.native.prevent="handleLogin"
+          >
+            <span v-if="!loading">鐧� 褰�</span>
+            <span v-else>鐧� 褰� 涓�...</span>
+          </el-button>
+          <div style="float: right;" v-if="register">
+            <router-link class="link-type" :to="'/register'">绔嬪嵆娉ㄥ唽</router-link>
+          </div>
+        </el-form-item>
+      </el-form>
+    </div>
+    <!--  搴曢儴  -->
+    <div class="el-login-footer">
+      <span>Copyright 漏 2018-2023 jcdm.vip All Rights Reserved.</span>
+    </div>
+  </div>
+</template>
+
+<script>
+import { getCodeImg } from "@/api/login";
+import Cookies from "js-cookie";
+import { encrypt, decrypt } from '@/utils/jsencrypt'
+
+export default {
+  name: "Login",
+  data() {
+    return {
+      codeUrl: "",
+      loginForm: {
+        username: "admin",
+        password: "admin123",
+        rememberMe: false,
+        code: "",
+        uuid: ""
+      },
+      loginRules: {
+        username: [
+          { required: true, trigger: "blur", message: "璇疯緭鍏ユ偍鐨勮处鍙�" }
+        ],
+        password: [
+          { required: true, trigger: "blur", message: "璇疯緭鍏ユ偍鐨勫瘑鐮�" }
+        ],
+        code: [{ required: true, trigger: "change", message: "璇疯緭鍏ラ獙璇佺爜" }]
+      },
+      loading: false,
+      // 楠岃瘉鐮佸紑鍏�
+      captchaEnabled: true,
+      // 娉ㄥ唽寮�鍏�
+      register: false,
+      redirect: undefined
+    };
+  },
+  watch: {
+    $route: {
+      handler: function(route) {
+        this.redirect = route.query && route.query.redirect;
+      },
+      immediate: true
+    }
+  },
+  created() {
+    this.getCode();
+    this.getCookie();
+  },
+  methods: {
+    getCode() {
+      getCodeImg().then(res => {
+        this.captchaEnabled = res.captchaEnabled === undefined ? true : res.captchaEnabled;
+        if (this.captchaEnabled) {
+          this.codeUrl = "data:image/gif;base64," + res.img;
+          this.loginForm.uuid = res.uuid;
+        }
+      });
+    },
+    getCookie() {
+      const username = Cookies.get("username");
+      const password = Cookies.get("password");
+      const rememberMe = Cookies.get('rememberMe')
+      this.loginForm = {
+        username: username === undefined ? this.loginForm.username : username,
+        password: password === undefined ? this.loginForm.password : decrypt(password),
+        rememberMe: rememberMe === undefined ? false : Boolean(rememberMe)
+      };
+    },
+    handleLogin() {
+      this.$refs.loginForm.validate(valid => {
+        if (valid) {
+          this.loading = true;
+          if (this.loginForm.rememberMe) {
+            Cookies.set("username", this.loginForm.username, { expires: 30 });
+            Cookies.set("password", encrypt(this.loginForm.password), { expires: 30 });
+            Cookies.set('rememberMe', this.loginForm.rememberMe, { expires: 30 });
+          } else {
+            Cookies.remove("username");
+            Cookies.remove("password");
+            Cookies.remove('rememberMe');
+          }
+          this.$store.dispatch("Login", this.loginForm).then(() => {
+            this.$router.push({ path: this.redirect || "/" }).catch(()=>{});
+          }).catch(() => {
+            this.loading = false;
+            if (this.captchaEnabled) {
+              this.getCode();
+            }
+          });
+        }
+      });
+    }
+  }
+};
+</script>
+
+<style rel="stylesheet/scss" lang="scss">
+.login {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  height: 100%;
+  //background-image: url("../assets/images/login-background.png");
+  background-size: cover;
+}
+
+.login-left {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  height: 100%;
+  width: 50%;
+  background-image: url("../assets/images/login-background.png");
+  background-size: cover;
+}
+
+.login-right {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  height: 100%;
+  width: 50%;
+  background-size: cover;
+}
+
+.title {
+  margin: 0px auto 30px auto;
+  text-align: center;
+  color: #707070;
+}
+
+.login-form {
+  border-radius: 6px;
+  background: #ffffff;
+  width: 400px;
+  padding: 25px 25px 5px 25px;
+  .el-input {
+    height: 38px;
+    input {
+      height: 38px;
+    }
+  }
+  .input-icon {
+    height: 39px;
+    width: 14px;
+    margin-left: 2px;
+  }
+}
+.login-tip {
+  font-size: 13px;
+  text-align: center;
+  color: #bfbfbf;
+}
+.login-code {
+  width: 33%;
+  height: 38px;
+  float: right;
+  img {
+    cursor: pointer;
+    vertical-align: middle;
+  }
+}
+.el-login-footer {
+  height: 40px;
+  line-height: 40px;
+  position: fixed;
+  bottom: 0;
+  width: 100%;
+  text-align: center;
+  color: #020202;
+  font-family: Arial;
+  font-size: 12px;
+  letter-spacing: 1px;
+}
+.login-code-img {
+  height: 38px;
+}
+</style>
diff --git a/jcdm-ui/src/views/main/bs/ProductBom/index.vue b/jcdm-ui/src/views/main/bs/ProductBom/index.vue
new file mode 100644
index 0000000..0e1ae51
--- /dev/null
+++ b/jcdm-ui/src/views/main/bs/ProductBom/index.vue
@@ -0,0 +1,391 @@
+<template>
+  <div class="app-container">
+    <el-card class="box-card">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label-width="120" label="BOM缂栫爜" prop="bomCode">
+        <el-input
+          v-model="queryParams.bomCode"
+          placeholder="璇疯緭鍏OM缂栫爜"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label-width="120" label="BOM鍚嶇О" prop="bomName">
+        <el-input
+          v-model="queryParams.bomName"
+          placeholder="璇疯緭鍏OM鍚嶇О"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="浜у搧缂栫爜" prop="productCode">
+        <el-input
+          v-model="queryParams.productCode"
+          placeholder="璇疯緭鍏ヤ骇鍝佺紪鐮�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="浜у搧鍚嶇О" prop="productName">
+        <el-input
+          v-model="queryParams.productName"
+          placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item style="float: right">
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+                  <el-button type="warning" icon="el-icon-copy-document" size="mini" @click="advancedQuery">楂樼骇鏌ヨ</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+      <el-form :model="queryParams" ref="queryParams" size="small" :inline="true" v-show="advancedShowSearch" label-width="68px">
+      <el-form-item label="鏁版嵁鏉ユ簮" prop="dataSource">
+        <el-input
+          v-model="queryParams.dataSource"
+          placeholder="璇疯緭鍏ユ暟鎹潵婧�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+        </el-form-item>
+      </el-form>
+    </el-card>
+
+    <el-card style="margin-top: 10px" class="box-card">
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['bs:ProductBom:add']"
+        >鏂板</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['bs:ProductBom:edit']"
+        >淇敼</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['bs:ProductBom:remove']"
+        >鍒犻櫎</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['bs:ProductBom:export']"
+        >瀵煎嚭</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" border :data="ProductBomList" @selection-change="handleSelectionChange" v-if="ProductBomList.length > 0">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="BOM缂栫爜" align="center" prop="bomCode">
+        <template slot-scope="scope">
+          <router-link :to="{path: '/main/bom-data/index/', query: {bomCode: scope.row.bomCode} }" class="link-type">
+            <span>{{ scope.row.bomCode }}</span>
+          </router-link>
+        </template>
+      </el-table-column>
+      <el-table-column label="BOM鍚嶇О" align="center" prop="bomName">
+      </el-table-column>
+      <el-table-column label="浜у搧缂栫爜" align="center" prop="productCode">
+      </el-table-column>
+      <el-table-column label="浜у搧鍚嶇О" align="center" prop="productName">
+      </el-table-column>
+      <el-table-column label="鐗堟湰" align="center" prop="version">
+      </el-table-column>
+      <el-table-column label="鐘舵��" align="center" prop="status">
+        <template slot-scope="scope">
+          <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="澶囨敞" align="center" prop="remark">
+      </el-table-column>
+      <el-table-column label="鍒涘缓鐢ㄦ埛" align="center" prop="createUser">
+      </el-table-column>
+      <el-table-column label="鏇存敼鐢ㄦ埛" align="center" prop="updateUser">
+      </el-table-column>
+      <el-table-column label="鏁版嵁鏉ユ簮" align="center" prop="dataSource">
+      </el-table-column>
+      <el-table-column fixed="right" label="鎿嶄綔" width="200" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="success"
+            plain
+            style="width: 72px"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['bs:ProductBom:edit']"
+          >淇敼</el-button>
+          <el-button
+            size="mini"
+            plain
+            style="width: 72px"
+            type="danger"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['bs:ProductBom:remove']"
+          >鍒犻櫎</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+      <el-empty v-else>
+        <span slot="description">鏆傛棤鏁版嵁</span>
+      </el-empty>
+    </el-card>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 娣诲姞鎴栦慨鏀瑰熀纭�BOM瀵硅瘽妗� -->
+    <el-dialog v-dialogpop-up :title="title" :visible.sync="open" width="500px" append-to-body>
+      <span slot="title">
+        <i class="el-icon-s-order"></i>
+        {{titleName}}
+      </span>
+      <el-form ref="form" :model="form" :rules="rules" label-width="100px">
+        <el-form-item label="BOM缂栫爜" prop="bomCode">
+          <el-input v-model="form.bomCode" placeholder="璇疯緭鍏OM缂栫爜" />
+        </el-form-item>
+        <el-form-item label="BOM鍚嶇О" prop="bomName">
+          <el-input v-model="form.bomName" placeholder="璇疯緭鍏OM鍚嶇О" />
+        </el-form-item>
+        <el-form-item label="浜у搧缂栫爜" prop="productCode">
+          <el-input v-model="form.productCode" placeholder="璇疯緭鍏ヤ骇鍝佺紪鐮�" />
+        </el-form-item>
+        <el-form-item label="浜у搧鍚嶇О" prop="productName">
+          <el-input v-model="form.productName" placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�" />
+        </el-form-item>
+<!--        <el-form-item label="鐗堟湰" prop="version">-->
+<!--          <el-input v-model="form.version" placeholder="璇疯緭鍏ョ増鏈�" />-->
+<!--        </el-form-item>-->
+        <el-form-item label="鐘舵��" prop="status">
+          <el-radio-group v-model="form.status">
+            <el-radio
+              v-for="dict in dict.type.sys_normal_disable"
+              :key="dict.value"
+              :label="dict.value"
+            >{{dict.label}}</el-radio>
+          </el-radio-group>
+        </el-form-item>
+<!--        <el-form-item label="棰勭暀瀛楁1" prop="spareField1">-->
+<!--          <el-input v-model="form.spareField1" placeholder="璇疯緭鍏ラ鐣欏瓧娈�1" />-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="棰勭暀瀛楁2" prop="spareField2">-->
+<!--          <el-input v-model="form.spareField2" placeholder="璇疯緭鍏ラ鐣欏瓧娈�2" />-->
+<!--        </el-form-item>-->
+
+<!--        <el-form-item label="鏁版嵁鏉ユ簮" prop="dataSource">-->
+<!--          <el-input v-model="form.dataSource" placeholder="璇疯緭鍏ユ暟鎹潵婧�" />-->
+<!--        </el-form-item>-->
+        <el-form-item label="澶囨敞" prop="remark">
+          <el-input v-model="form.remark" placeholder="璇疯緭鍏ュ娉�" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listProductBom, getProductBom, delProductBom, addProductBom, updateProductBom } from "@/api/main/bs/ProductBom/ProductBom";
+
+export default {
+  name: "ProductBom",
+  dicts: ['sys_normal_disable'],
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      titleName: 'test',
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 鍩虹BOM琛ㄦ牸鏁版嵁
+      ProductBomList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      advancedShowSearch: false,
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        bomCode: null,
+        bomName: null,
+        productCode: null,
+        productName: null,
+        dataSource: null
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        id: [
+          { required: true, message: "涓婚敭id涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        bomCode: [
+          { required: true, message: "BOM缂栫爜涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        productCode: [
+          { required: true, message: "浜у搧缂栫爜涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        status: [
+          { required: true, message: "鐘舵��(瀛楀吀)涓嶈兘涓虹┖", trigger: "change" }
+        ],
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    advancedQuery(){
+      this.advancedShowSearch = (this.advancedShowSearch) ? this.advancedShowSearch = false : this.advancedShowSearch = true;
+    },
+    /** 鏌ヨ鍩虹BOM鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listProductBom(this.queryParams).then(response => {
+        this.ProductBomList = response.rows;
+        console.log(this.ProductBomList)
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        id: null,
+        bomCode: null,
+        bomName: null,
+        productCode: null,
+        productName: null,
+        version: null,
+        status: null,
+        spareField1: null,
+        spareField2: null,
+        remark: null,
+        createUser: null,
+        createTime: null,
+        updateUser: null,
+        updateTime: null,
+        dataSource: null
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.titleName = "娣诲姞鍩虹BOM";
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getProductBom(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.titleName = "淇敼鍩虹BOM";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateProductBom(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addProductBom(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎鍩虹BOM缂栧彿涓�"' + ids + '"鐨勬暟鎹」锛�').then(function() {
+        return delProductBom(ids);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('bs/ProductBom/export', {
+        ...this.queryParams
+      }, `ProductBom_${new Date().getTime()}.xlsx`)
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/main/bs/ProductBomChild/index.vue b/jcdm-ui/src/views/main/bs/ProductBomChild/index.vue
new file mode 100644
index 0000000..4e34ecf
--- /dev/null
+++ b/jcdm-ui/src/views/main/bs/ProductBomChild/index.vue
@@ -0,0 +1,457 @@
+<template>
+  <div class="app-container">
+    <el-card class="box-card">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="宸ュ簭缂栫爜" prop="opCode">
+        <el-input
+          v-model="queryParams.opCode"
+          placeholder="璇疯緭鍏ュ伐搴忕紪鐮�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="宸ュ簭鍚嶇О" prop="opName">
+        <el-input
+          v-model="queryParams.opName"
+          placeholder="璇疯緭鍏ュ伐搴忓悕绉�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="鐗╂枡缂栫爜" prop="materialCode">
+        <el-input
+          v-model="queryParams.materialCode"
+          placeholder="璇疯緭鍏ョ墿鏂欑紪鐮�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="鐗╂枡鍚嶇О" label-width="120" prop="materialName">
+        <el-input
+          v-model="queryParams.materialName"
+          placeholder="璇疯緭鍏ョ墿鏂欏悕绉�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item style="float: right">
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+    </el-card>
+
+    <el-card style="margin-top: 10px" class="box-card">
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['bs:ProductBomChild:add']"
+        >鏂板</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['bs:ProductBomChild:edit']"
+        >淇敼</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['bs:ProductBomChild:remove']"
+        >鍒犻櫎</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['bs:ProductBomChild:export']"
+        >瀵煎嚭</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-close"
+          size="mini"
+          @click="handleClose"
+        >鍏抽棴</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-descriptions class="margin-top" :column="4" :size="size" border>
+      <el-descriptions-item :span="1">
+        <template slot="label">
+          <i class="el-icon-user"></i>
+          BOM缂栫爜
+        </template>
+        {{headerInformationData.bomCode}}
+      </el-descriptions-item>
+      <el-descriptions-item :span="1">
+        <template slot="label">
+          <i class="el-icon-mobile-phone"></i>
+          BOM鍚嶇О
+        </template>
+        {{headerInformationData.bomName}}
+      </el-descriptions-item>
+      <el-descriptions-item :span="1">
+        <template slot="label">
+          <i class="el-icon-location-outline"></i>
+          浜у搧缂栫爜
+        </template>
+        {{headerInformationData.productCode}}
+      </el-descriptions-item>
+      <el-descriptions-item :span="1">
+        <template slot="label">
+          <i class="el-icon-tickets"></i>
+          浜у搧鍚嶇О
+        </template>
+        {{headerInformationData.productName}}
+      </el-descriptions-item>
+    </el-descriptions>
+
+    <el-table v-loading="loading"  border :data="ProductBomChildList" @selection-change="handleSelectionChange" v-if="ProductBomChildList.length > 0">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="宸ュ簭缂栫爜" align="center" prop="opCode">
+      </el-table-column>
+      <el-table-column label="宸ュ簭鍚嶇О" align="center" prop="opName">
+      </el-table-column>
+      <el-table-column label="鐗╂枡缂栫爜" align="center" prop="materialCode">
+      </el-table-column>
+      <el-table-column label="鐗╂枡鍚嶇О" align="center" prop="materialName">
+      </el-table-column>
+      <el-table-column label="鍗曡��" align="center" prop="costQty">
+      </el-table-column>
+      <el-table-column label="鍗曚綅" align="center" prop="unit">
+      </el-table-column>
+      <el-table-column label="澶囨敞" align="center" prop="remark">
+      </el-table-column>
+      <el-table-column label="BOM缂栫爜" align="center" prop="bomCode">
+      </el-table-column>
+      <el-table-column fixed="right" label="鎿嶄綔" width="200" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="success"
+            plain
+            style="width: 72px"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['bs:ProductBomChild:edit']"
+          >淇敼</el-button>
+          <el-button
+            size="mini"
+            plain
+            style="width: 72px"
+            type="danger"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['bs:ProductBomChild:remove']"
+          >鍒犻櫎</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+      <el-empty v-else>
+        <span slot="description">鏆傛棤鏁版嵁</span>
+      </el-empty>
+    </el-card>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 娣诲姞鎴栦慨鏀瑰熀纭�BOM瀛愪俊鎭璇濇 -->
+    <el-dialog v-dialogpop-up :title="title" :visible.sync="open" width="500px" append-to-body>
+      <span slot="title">
+        <i class="el-icon-s-order"></i>
+        {{titleName}}
+      </span>
+      <el-form ref="form" :model="form" :rules="rules" label-width="120px">
+        <el-form-item label="BOM缂栫爜" prop="bomCode">
+          <el-input v-model="querybomCode" :disabled="true" />
+        </el-form-item>
+<!--        <el-form-item label="鐗╂枡缂栫爜" prop="materialCode">-->
+<!--          <el-input v-model="form.materialCode" placeholder="璇疯緭鍏ョ墿鏂欑紪鐮�" />-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="鐗╂枡鍚嶇О" prop="materialName">-->
+<!--          <el-input v-model="form.materialName" placeholder="璇疯緭鍏ョ墿鏂欏悕绉�" />-->
+<!--        </el-form-item>-->
+        <el-form-item label="鐗╂枡缂栫爜" prop="productCode">
+          <el-input v-model="form.materialCode" placeholder="璇烽�夋嫨浜у搧" >
+            <el-button slot="append" @click="handleSelectProduct" icon="el-icon-search"></el-button>
+          </el-input>
+          <ItemSelect ref="itemSelect" @onSelected="onItemSelected" > </ItemSelect>
+        </el-form-item>
+        <el-form-item label="鐗╂枡鍚嶇О" prop="materialName">
+          <el-input disabled v-model="form.materialName" placeholder="璇疯緭鍏ョ墿鏂欏悕绉�" />
+        </el-form-item>
+        <el-form-item label="鍗曡��" prop="costQty">
+          <el-input v-model="form.costQty" placeholder="璇疯緭鍏ュ崟鑰�" />
+        </el-form-item>
+        <el-form-item label="鍗曚綅" prop="unit">
+          <el-input v-model="form.unit" placeholder="璇疯緭鍏ュ崟浣�" />
+        </el-form-item>
+        <el-form-item label="宸ュ簭缂栫爜" prop="opCode">
+          <el-input v-model="form.opCode" placeholder="璇疯緭鍏ュ伐搴忕紪鐮�" />
+        </el-form-item>
+        <el-form-item label="宸ュ簭鍚嶇О" prop="opName">
+          <el-input v-model="form.opName" placeholder="璇疯緭鍏ュ伐搴忓悕绉�" />
+        </el-form-item>
+<!--        <el-form-item label="棰勭暀瀛楁1" prop="spareField1">-->
+<!--          <el-input v-model="form.spareField1" placeholder="璇疯緭鍏ラ鐣欏瓧娈�1" />-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="棰勭暀瀛楁2" prop="spareField2">-->
+<!--          <el-input v-model="form.spareField2" placeholder="璇疯緭鍏ラ鐣欏瓧娈�2" />-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="棰勭暀瀛楁3" prop="spareField3">-->
+<!--          <el-input v-model="form.spareField3" placeholder="璇疯緭鍏ラ鐣欏瓧娈�3" />-->
+<!--        </el-form-item>-->
+        <el-form-item label="澶囨敞" prop="remark">
+          <el-input v-model="form.remark" placeholder="璇疯緭鍏ュ娉�" />
+        </el-form-item>
+<!--        <el-form-item label="BOM涓昏〃ID" prop="bomInfoId">-->
+<!--          <el-input v-model="form.bomInfoId" placeholder="璇疯緭鍏OM涓昏〃ID" />-->
+<!--        </el-form-item>-->
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listProductBomChild, getProductBomChild, delProductBomChild, addProductBomChild, updateProductBomChild } from "@/api/main/bs/ProductBomChild/ProductBomChild";
+import {listProcesses} from "@/api/main/bs/processes/processes";
+import {listProductBom} from "@/api/main/bs/ProductBom/ProductBom";
+import {listTechnologyRoute} from "@/api/main/bs/technologyRoute/technologyRoute";
+import ItemSelect from "@/components/itemSelect/single.vue";
+
+export default {
+  name: "ProductBomChild",
+  components: {
+    ItemSelect ,
+  },
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      titleName: 'test',
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 鍩虹BOM瀛愪俊鎭〃鏍兼暟鎹�
+      ProductBomChildList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      querybomCode: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        materialCode: null,
+        bomCode: null,
+        opCode: null,
+        opName: null,
+        materialName: null,
+      },
+      headerInformationData:{
+        bomCode: "",
+        bomName: "",
+        productCode: "",
+        productName: ""
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        id: [
+          { required: true, message: "涓婚敭id涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        costQty: [
+          { required: true, message: "鍗曡�椾笉鑳戒负绌�", trigger: "blur" }
+        ],
+        unit: [
+          { required: true, message: "鍗曚綅涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        bomCode: [
+          { required: true, message: "BOM缂栫爜涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+      }
+    };
+  },
+  created() {
+
+    let bomCode = this.$route.query.bomCode;
+    this.queryParams.bomCode = bomCode
+    this.querybomCode = bomCode
+    this.getList();
+    this.headerInformation();
+    this.getProcesses();
+  },
+  methods: {
+    //鐗╂枡閫夋嫨寮瑰嚭妗�
+    onItemSelected(obj){
+      if(obj !== undefined && obj !== null){
+        this.form.materialCode = obj.materialCode;
+        this.form.materialName = obj.materialName;
+      }
+    },
+    handleSelectProduct(){
+      this.$refs.itemSelect.showFlag = true;
+    },
+    getProcesses() {
+      listProcesses(null).then(response => {
+        this.options = response.rows;
+      });
+    },
+    /** BOM琛ㄥご淇℃伅 */
+    headerInformation() {
+      listProductBom(this.queryParams).then(response => {
+        this.headerInformationData = response.rows[0];
+        //this.$modal.msgSuccess(this.headerInformationData.bomCode);
+      });
+    },
+    /** 杩斿洖鎸夐挳鎿嶄綔 */
+    handleClose() {
+      const obj = { path: "/main/pm/ProductBom" };
+      this.$tab.closeOpenPage(obj);
+    },
+    /** 鏌ヨ鍩虹BOM瀛愪俊鎭垪琛� */
+    getList() {
+      this.loading = true;
+      listProductBomChild(this.queryParams).then(response => {
+        this.ProductBomChildList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        id: null,
+        opCode: null,
+        opName: null,
+        materialCode: null,
+        materialName: null,
+        costQty: null,
+        unit: null,
+        spareField1: null,
+        spareField2: null,
+        spareField3: null,
+        remark: null,
+        bomCode: null,
+        bomInfoId: null
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.titleName = "娣诲姞BOM瀛愪俊鎭�";
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getProductBomChild(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.titleName = "淇敼鍩虹BOM瀛愪俊鎭�";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm() {
+      this.form.bomCode = this.querybomCode;
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateProductBomChild(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addProductBomChild(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎鍩虹BOM瀛愪俊鎭紪鍙蜂负"' + ids + '"鐨勬暟鎹」锛�').then(function() {
+        return delProductBomChild(ids);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('bs/ProductBomChild/export', {
+        ...this.queryParams
+      }, `ProductBomChild_${new Date().getTime()}.xlsx`)
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/main/bs/beatSetting/index.vue b/jcdm-ui/src/views/main/bs/beatSetting/index.vue
new file mode 100644
index 0000000..6179c36
--- /dev/null
+++ b/jcdm-ui/src/views/main/bs/beatSetting/index.vue
@@ -0,0 +1,336 @@
+<template>
+  <div class="app-container">
+    <el-card class="box-card">
+        <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+          <el-form-item label="浜у搧缂栫爜" prop="productCode">
+            <el-input
+              v-model="queryParams.productCode"
+              placeholder="璇疯緭鍏ヤ骇鍝佺紪鐮�"
+              clearable
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item label="浜у搧鍚嶇О" prop="productName">
+            <el-input
+              v-model="queryParams.productName"
+              placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�"
+              clearable
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item style="float: right">
+            <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+            <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+          </el-form-item>
+        </el-form>
+    </el-card>
+
+    <el-card style="margin-top: 10px" class="box-card">
+        <el-row :gutter="10" class="mb8">
+          <el-col :span="1.5">
+            <el-button
+              type="primary"
+              plain
+              icon="el-icon-plus"
+              size="mini"
+              @click="handleAdd"
+              v-hasPermi="['bs:beatSetting:add']"
+            >鏂板</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="success"
+              plain
+              icon="el-icon-edit"
+              size="mini"
+              :disabled="single"
+              @click="handleUpdate"
+              v-hasPermi="['bs:beatSetting:edit']"
+            >淇敼</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="danger"
+              plain
+              icon="el-icon-delete"
+              size="mini"
+              :disabled="multiple"
+              @click="handleDelete"
+              v-hasPermi="['bs:beatSetting:remove']"
+            >鍒犻櫎</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="warning"
+              plain
+              icon="el-icon-download"
+              size="mini"
+              @click="handleExport"
+              v-hasPermi="['bs:beatSetting:export']"
+            >瀵煎嚭</el-button>
+          </el-col>
+          <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+        </el-row>
+
+        <el-table border v-loading="loading" :data="beatSettingList" @selection-change="handleSelectionChange">
+          <el-table-column type="selection" width="55" align="center" />
+          <el-table-column label="浜у搧缂栫爜" align="center" prop="productCode">
+          </el-table-column>
+          <el-table-column label="浜у搧鍚嶇О" align="center" prop="productName">
+          </el-table-column>
+          <el-table-column label="鑺傛媿" align="center" prop="beat">
+          </el-table-column>
+          <el-table-column fixed="right" width="200" label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+            <template slot-scope="scope">
+              <el-button
+                size="mini"
+                type="success"
+                plain
+                style="width: 72px"
+                icon="el-icon-edit"
+                @click="handleUpdate(scope.row)"
+                v-hasPermi="['bs:beatSetting:edit']"
+              >淇敼</el-button>
+              <el-button
+                size="mini"
+                type="danger"
+                plain
+                style="width: 72px"
+                icon="el-icon-delete"
+                @click="handleDelete(scope.row)"
+                v-hasPermi="['bs:beatSetting:remove']"
+              >鍒犻櫎</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+    </el-card>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 娣诲姞鎴栦慨鏀硅妭鎷嶈缃璇濇 -->
+    <el-dialog v-dialogpop-up :title="title" :visible.sync="open" width="500px" append-to-body>
+      <span slot="title">
+        <i class="el-icon-s-order"></i>
+        {{titleName}}
+      </span>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="浜у搧缂栫爜" prop="productCode">
+          <el-select style="width: 100%" @change="handleSelectChange(form.productCode)" v-model="form.productCode" placeholder="璇疯緭鍏ヤ骇鍝佺紪鐮�">
+            <el-option
+              v-for="item in options"
+              :key="item.productCode"
+              :label="item.productCode"
+              :value="item.productCode">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item  label="浜у搧鍚嶇О" prop="productName">
+          <el-input  disabled v-model="form.productName" placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�" />
+        </el-form-item>
+        <el-form-item label="鑺傛媿" prop="beat">
+          <el-input v-model="form.beat" placeholder="璇疯緭鍏ヨ妭鎷�" />
+        </el-form-item>
+        <el-form-item label="澶囨敞" prop="remark">
+          <el-input v-model="form.remark" placeholder="璇疯緭鍏ュ娉�" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listBeatSetting, getBeatSetting, delBeatSetting, addBeatSetting, updateBeatSetting } from "@/api/main/bs/beatSetting/beatSetting";
+import {listProductBom} from "@/api/main/bs/ProductBom/ProductBom";
+
+export default {
+  name: "BeatSetting",
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      titleName: "",
+      options: [],
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 鑺傛媿璁剧疆琛ㄦ牸鏁版嵁
+      beatSettingList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        productCode: null,
+        productName: null,
+        beat: null,
+        spareField1: null,
+        spareField2: null,
+        createUser: null,
+        updateUser: null,
+        dataSource: null
+      },
+      productCodeQueryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        productCode: null,
+        productName: null,
+        beat: null,
+        spareField1: null,
+        spareField2: null,
+        createUser: null,
+        updateUser: null,
+        dataSource: null
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        id: [
+          { required: true, message: "涓婚敭id涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        beat: [
+          { required: true, message: "鑺傛媿涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+      }
+    };
+  },
+  created() {
+    this.getList();
+    this.initProductBom();
+  },
+  methods: {
+    /** 鏌ヨ鑺傛媿璁剧疆鍒楄〃 */
+    handleSelectChange(selectedOption) {
+      this.productCodeQueryParams.productCode = selectedOption;
+      listProductBom(this.productCodeQueryParams).then(response => {
+        this.form.productName = response.rows[0].productName;
+      });
+    },
+    initProductBom(){
+      listProductBom(this.queryParams).then(response => {
+        this.options = response.rows;
+      });
+    },
+
+    getList() {
+      this.loading = true;
+      listBeatSetting(this.queryParams).then(response => {
+        this.beatSettingList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        id: null,
+        productCode: null,
+        productName: null,
+        beat: null,
+        spareField1: null,
+        spareField2: null,
+        remark: null,
+        createUser: null,
+        createTime: null,
+        updateUser: null,
+        updateTime: null,
+        dataSource: null
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.titleName = "娣诲姞鑺傛媿璁剧疆";
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getBeatSetting(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.titleName = "淇敼鑺傛媿璁剧疆";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateBeatSetting(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addBeatSetting(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎鑺傛媿璁剧疆缂栧彿涓�"' + ids + '"鐨勬暟鎹」锛�').then(function() {
+        return delBeatSetting(ids);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('bs/beatSetting/export', {
+        ...this.queryParams
+      }, `beatSetting_${new Date().getTime()}.xlsx`)
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/main/bs/formula/index.vue b/jcdm-ui/src/views/main/bs/formula/index.vue
new file mode 100644
index 0000000..c43aeca
--- /dev/null
+++ b/jcdm-ui/src/views/main/bs/formula/index.vue
@@ -0,0 +1,353 @@
+<template>
+  <div class="app-container">
+    <el-card class="box-card">
+        <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+          <el-form-item label="閰嶆柟缂栫爜" prop="formulaCode">
+            <el-input
+              v-model="queryParams.formulaCode"
+              placeholder="璇疯緭鍏ラ厤鏂圭紪鐮�"
+              clearable
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item label="閰嶆柟鍚嶇О" prop="formulaName">
+            <el-input
+              v-model="queryParams.formulaName"
+              placeholder="璇疯緭鍏ラ厤鏂瑰悕绉�"
+              clearable
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+<!--          <el-form-item label="鐘舵��" prop="status">-->
+<!--            <el-select v-model="queryParams.status" placeholder="璇烽�夋嫨鐘舵��" clearable>-->
+<!--              <el-option-->
+<!--                v-for="dict in dict.type.${dictType}"-->
+<!--                :key="dict.value"-->
+<!--                :label="dict.label"-->
+<!--                :value="dict.value"-->
+<!--              />-->
+<!--            </el-select>-->
+<!--          </el-form-item>-->
+          <el-form-item label="浜у搧缂栫爜" prop="productCode">
+            <el-input
+              v-model="queryParams.productCode"
+              placeholder="璇疯緭鍏ヤ骇鍝佺紪鐮�"
+              clearable
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item style="float: right">
+            <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+            <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+          </el-form-item>
+        </el-form>
+    </el-card>
+
+    <el-card style="margin-top: 10px" class="box-card">
+        <el-row :gutter="10" class="mb8">
+          <el-col :span="1.5">
+            <el-button
+              type="primary"
+              plain
+              icon="el-icon-plus"
+              size="mini"
+              @click="handleAdd"
+              v-hasPermi="['bs:formula:add']"
+            >鏂板</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="success"
+              plain
+              icon="el-icon-edit"
+              size="mini"
+              :disabled="single"
+              @click="handleUpdate"
+              v-hasPermi="['bs:formula:edit']"
+            >淇敼</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="danger"
+              plain
+              icon="el-icon-delete"
+              size="mini"
+              :disabled="multiple"
+              @click="handleDelete"
+              v-hasPermi="['bs:formula:remove']"
+            >鍒犻櫎</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="warning"
+              plain
+              icon="el-icon-download"
+              size="mini"
+              @click="handleExport"
+              v-hasPermi="['bs:formula:export']"
+            >瀵煎嚭</el-button>
+          </el-col>
+          <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+        </el-row>
+
+        <el-table border v-loading="loading" :data="formulaList" @selection-change="handleSelectionChange">
+          <el-table-column type="selection" width="55" align="center" />
+<!--          <el-table-column label="閰嶆柟缂栫爜" width="130" align="center" prop="formulaCode">-->
+<!--          </el-table-column>-->
+          <el-table-column label="閰嶆柟缂栫爜" width="130" align="center" :show-overflow-tooltip="true">
+            <template slot-scope="scope">
+              <router-link :to="{path: '/main/formula-data/index/', query: {formulaCode: scope.row.formulaCode} }" class="link-type">
+
+                <span>{{ scope.row.formulaCode }}</span>
+              </router-link>
+            </template>
+          </el-table-column>
+          <el-table-column label="閰嶆柟鍚嶇О" width="150" align="center" prop="formulaName">
+          </el-table-column>
+          <el-table-column label="鐘舵��" width="90" align="center" prop="status">
+          </el-table-column>
+          <el-table-column label="浜у搧缂栫爜" width="130" align="center" prop="productCode">
+          </el-table-column>
+          <el-table-column label="澶囨敞" width="130" align="center" prop="remark">
+          </el-table-column>
+          <el-table-column label="鍒涘缓鐢ㄦ埛" width="150" align="center" prop="createUser">
+          </el-table-column>
+          <el-table-column label="鍒涘缓鏃堕棿" width="160" align="center" prop="createTime">
+          </el-table-column>
+          <el-table-column label="鏇存敼鐢ㄦ埛" width="150" align="center" prop="updateUser">
+          </el-table-column>
+          <el-table-column label="鏇存敼鏃堕棿" width="160" align="center" prop="updateTime">
+          </el-table-column>
+          <el-table-column fixed="right" width="200" label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+            <template slot-scope="scope">
+              <el-button
+                size="mini"
+                type="success"
+                plain
+                style="width: 72px"
+                icon="el-icon-edit"
+                @click="handleUpdate(scope.row)"
+                v-hasPermi="['bs:formula:edit']"
+              >淇敼</el-button>
+              <el-button
+                size="mini"
+                type="danger"
+                plain
+                style="width: 72px"
+                icon="el-icon-delete"
+                @click="handleDelete(scope.row)"
+                v-hasPermi="['bs:formula:remove']"
+              >鍒犻櫎</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+    </el-card>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 娣诲姞鎴栦慨鏀归厤鏂归厤缃璇濇 -->
+    <el-dialog v-dialogpop-up :title="title" :visible.sync="open" width="500px" append-to-body>
+      <span slot="title">
+        <i class="el-icon-s-order"></i>
+        {{titleName}}
+      </span>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="閰嶆柟缂栫爜" prop="formulaCode">
+          <el-input v-model="form.formulaCode" placeholder="璇疯緭鍏ラ厤鏂圭紪鐮�" />
+        </el-form-item>
+        <el-form-item label="閰嶆柟鍚嶇О" prop="formulaName">
+          <el-input v-model="form.formulaName" placeholder="璇疯緭鍏ラ厤鏂瑰悕绉�" />
+        </el-form-item>
+<!--        <el-form-item label="鐘舵��" prop="status">-->
+<!--          <el-radio-group v-model="form.status">-->
+<!--            <el-radio-->
+<!--              v-for="dict in dict.type.${dictType}"-->
+<!--              :key="dict.value"-->
+<!--              :label="dict.value"-->
+<!--            >{{dict.label}}</el-radio>-->
+<!--          </el-radio-group>-->
+<!--        </el-form-item>-->
+        <el-form-item label="浜у搧缂栫爜" prop="productCode">
+          <el-input v-model="form.productCode" placeholder="璇疯緭鍏ヤ骇鍝佺紪鐮�" />
+        </el-form-item>
+        <el-form-item label="澶囨敞" prop="remark">
+          <el-input v-model="form.remark" placeholder="璇疯緭鍏ュ娉�" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listFormula, getFormula, delFormula, addFormula, updateFormula } from "@/api/main/bs/formula/formula";
+
+export default {
+  name: "Formula",
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      titleName: "",
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 閰嶆柟閰嶇疆琛ㄦ牸鏁版嵁
+      formulaList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        formulaCode: null,
+        formulaName: null,
+        status: null,
+        productCode: null,
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        id: [
+          { required: true, message: "涓婚敭id涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        formulaCode: [
+          { required: true, message: "閰嶆柟缂栫爜涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        status: [
+          { required: true, message: "鐘舵�佷笉鑳戒负绌�", trigger: "change" }
+        ],
+        productCode: [
+          { required: true, message: "浜у搧缂栫爜涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 鏌ヨ閰嶆柟閰嶇疆鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listFormula(this.queryParams).then(response => {
+        this.formulaList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        id: null,
+        formulaCode: null,
+        formulaName: null,
+        status: null,
+        productCode: null,
+        remark: null,
+        createUser: null,
+        createTime: null,
+        updateUser: null,
+        updateTime: null,
+        spareField1: null,
+        spareField2: null,
+        spareField3: null,
+        spareField4: null
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.titleName = "娣诲姞閰嶆柟閰嶇疆";
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getFormula(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.titleName = "淇敼閰嶆柟閰嶇疆";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateFormula(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addFormula(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎閰嶆柟閰嶇疆缂栧彿涓�"' + ids + '"鐨勬暟鎹」锛�').then(function() {
+        return delFormula(ids);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('bs/formula/export', {
+        ...this.queryParams
+      }, `formula_${new Date().getTime()}.xlsx`)
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/main/bs/formulaChild/index.vue b/jcdm-ui/src/views/main/bs/formulaChild/index.vue
new file mode 100644
index 0000000..95a80ea
--- /dev/null
+++ b/jcdm-ui/src/views/main/bs/formulaChild/index.vue
@@ -0,0 +1,474 @@
+<template>
+  <div class="app-container">
+    <el-card class="box-card">
+        <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+          <el-form-item label="杞﹂棿" prop="workshopCode">
+            <el-input
+              v-model="queryParams.workshopCode"
+              placeholder="璇疯緭鍏ヨ溅闂�"
+              clearable
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item label="浜х嚎" prop="lineCode">
+            <el-input
+              v-model="queryParams.lineCode"
+              placeholder="璇疯緭鍏ヤ骇绾�"
+              clearable
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item label="宸ュ簭" prop="processesCode">
+            <el-input
+              v-model="queryParams.processesCode"
+              placeholder="璇疯緭鍏ュ伐搴�"
+              clearable
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item label="浜у搧缂栧彿" prop="productCode">
+            <el-input
+              v-model="queryParams.productCode"
+              placeholder="璇疯緭鍏ヤ骇鍝佺紪鍙�"
+              clearable
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+<!--          <el-form-item label="绫诲瀷" prop="operationType">-->
+<!--            <el-select v-model="queryParams.operationType" placeholder="璇烽�夋嫨绫诲瀷" clearable>-->
+<!--              <el-option-->
+<!--                v-for="dict in dict.type.${dictType}"-->
+<!--                :key="dict.value"-->
+<!--                :label="dict.label"-->
+<!--                :value="dict.value"-->
+<!--              />-->
+<!--            </el-select>-->
+<!--          </el-form-item>-->
+          <el-form-item style="float: right">
+            <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+            <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+          </el-form-item>
+        </el-form>
+    </el-card>
+
+    <el-card style="margin-top: 10px" class="box-card">
+        <el-row :gutter="10" class="mb8">
+          <el-col :span="1.5">
+            <el-button
+              type="primary"
+              plain
+              icon="el-icon-plus"
+              size="mini"
+              @click="handleAdd"
+              v-hasPermi="['bs:formulaChild:add']"
+            >鏂板</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="success"
+              plain
+              icon="el-icon-edit"
+              size="mini"
+              :disabled="single"
+              @click="handleUpdate"
+              v-hasPermi="['bs:formulaChild:edit']"
+            >淇敼</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="danger"
+              plain
+              icon="el-icon-delete"
+              size="mini"
+              :disabled="multiple"
+              @click="handleDelete"
+              v-hasPermi="['bs:formulaChild:remove']"
+            >鍒犻櫎</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="warning"
+              plain
+              icon="el-icon-download"
+              size="mini"
+              @click="handleExport"
+              v-hasPermi="['bs:formulaChild:export']"
+            >瀵煎嚭</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="warning"
+              plain
+              icon="el-icon-close"
+              size="mini"
+              @click="handleClose"
+            >鍏抽棴</el-button>
+          </el-col>
+          <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+        </el-row>
+
+        <el-descriptions class="margin-top" :column="4" border>
+          <el-descriptions-item :span="1">
+            <template slot="label">
+              <i class="el-icon-user"></i>
+              閰嶆柟缂栫爜
+            </template>
+            {{headerInformationData.formulaCode}}
+          </el-descriptions-item>
+          <el-descriptions-item :span="1">
+            <template slot="label">
+              <i class="el-icon-mobile-phone"></i>
+              閰嶆柟鍚嶇О
+            </template>
+            {{headerInformationData.formulaName}}
+          </el-descriptions-item>
+          <el-descriptions-item :span="1">
+            <template slot="label">
+              <i class="el-icon-location-outline"></i>
+              浜у搧缂栫爜
+            </template>
+            {{headerInformationData.productCode}}
+          </el-descriptions-item>
+          <el-descriptions-item :span="1">
+            <template slot="label">
+              <i class="el-icon-tickets"></i>
+              浜у搧鍚嶇О
+            </template>
+<!--            {{headerInformationData.productName}}-->
+          </el-descriptions-item>
+        </el-descriptions>
+
+        <el-table border v-loading="loading" :data="formulaChildList" @selection-change="handleSelectionChange">
+          <el-table-column type="selection" width="55" align="center" />
+<!--          <el-table-column label="杞﹂棿" align="center" prop="workshopCode">-->
+<!--          </el-table-column>-->
+<!--          <el-table-column label="浜х嚎" align="center" prop="lineCode">-->
+<!--          </el-table-column>-->
+          <el-table-column label="宸ュ簭" width="90" align="center" prop="processesCode">
+          </el-table-column>
+          <el-table-column label="浜у搧缂栧彿" width="150" align="center" prop="productCode">
+          </el-table-column>
+          <el-table-column label="鎿嶄綔鍐呭" :show-overflow-tooltip='true' width="150" align="center" prop="operationSteps">
+          </el-table-column>
+          <el-table-column label="鎶�鏈姹�"  width="150" :show-overflow-tooltip='true' align="center" prop="techRequirement">
+          </el-table-column>
+          <el-table-column label="绫诲瀷" width="90" align="center" prop="operationType">
+            <template slot-scope="scope">
+              <dict-tag :options="dict.type.operation_type" :value="scope.row.operationType"/>
+            </template>
+          </el-table-column>
+          <el-table-column label="鎺掑簭" width="90" align="center" prop="stepSort">
+          </el-table-column>
+          <el-table-column label="鍙傛暟缂栫爜" :show-overflow-tooltip='true' width="130" align="center" prop="paramCode">
+          </el-table-column>
+          <el-table-column label="鐗╂枡缂栫爜" :show-overflow-tooltip='true' width="130" align="center" prop="materialCode">
+          </el-table-column>
+          <el-table-column label="閰嶆柟缂栫爜" width="130" align="center" prop="formulaCode">
+          </el-table-column>
+          <el-table-column label="鍥剧墖" :show-overflow-tooltip='true' width="130" align="center" prop="picture">
+<!--            <template slot-scope="scope">-->
+<!--              <el-image-->
+<!--                style="width: 100px; height: 100px"-->
+<!--                :src="pjtUrl+scope.row.picture"-->
+<!--                :fit="fit">-->
+<!--              </el-image>-->
+<!--            </template>-->
+          </el-table-column>
+          <el-table-column label="澶囨敞" width="130" align="center" prop="remarks">
+          </el-table-column>
+          <el-table-column label="鍒涘缓鐢ㄦ埛" width="130" align="center" prop="createUser">
+          </el-table-column>
+          <el-table-column label="鍒涘缓鏃堕棿" width="150" align="center" prop="createTime">
+          </el-table-column>
+          <el-table-column label="鏇存敼鐢ㄦ埛" width="130" align="center" prop="updateUser">
+          </el-table-column>
+          <el-table-column label="鏇存敼鏃堕棿" width="160" align="center" prop="updateTime">
+          </el-table-column>
+          <el-table-column fixed="right" width="200" label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+            <template slot-scope="scope">
+              <el-button
+                size="mini"
+                type="success"
+                plain
+                style="width: 72px"
+                icon="el-icon-edit"
+                @click="handleUpdate(scope.row)"
+                v-hasPermi="['bs:formulaChild:edit']"
+              >淇敼</el-button>
+              <el-button
+                size="mini"
+                type="danger"
+                plain
+                style="width: 72px"
+                icon="el-icon-delete"
+                @click="handleDelete(scope.row)"
+                v-hasPermi="['bs:formulaChild:remove']"
+              >鍒犻櫎</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+    </el-card>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 娣诲姞鎴栦慨鏀归厤鏂归厤缃瓙淇℃伅瀵硅瘽妗� -->
+    <el-dialog v-dialogpop-up :title="title" :visible.sync="open" width="500px" append-to-body>
+      <span slot="title">
+        <i class="el-icon-s-order"></i>
+        {{titleName}}
+      </span>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+<!--        <el-form-item label="杞﹂棿" prop="workshopCode">-->
+<!--          <el-input v-model="form.workshopCode" placeholder="璇疯緭鍏ヨ溅闂�" />-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="浜х嚎" prop="lineCode">-->
+<!--          <el-input v-model="form.lineCode" placeholder="璇疯緭鍏ヤ骇绾�" />-->
+<!--        </el-form-item>-->
+        <el-form-item label="閰嶆柟缂栫爜">
+          <el-input v-model="formulaCode" :disabled="true" />
+        </el-form-item>
+        <el-form-item label="宸ュ簭" prop="processesCode">
+          <el-input v-model="form.processesCode" placeholder="璇疯緭鍏ュ伐搴�" />
+        </el-form-item>
+        <el-form-item label="浜у搧缂栧彿" prop="productCode">
+          <el-input v-model="form.productCode" placeholder="璇疯緭鍏ヤ骇鍝佺紪鍙�" />
+        </el-form-item>
+        <el-form-item label="鎿嶄綔鍐呭" prop="operationSteps">
+          <el-input v-model="form.operationSteps" placeholder="璇疯緭鍏ユ搷浣滃唴瀹�" />
+        </el-form-item>
+        <el-form-item label="鎶�鏈姹�" prop="techRequirement">
+          <el-input v-model="form.techRequirement" placeholder="璇疯緭鍏ユ妧鏈姹�" />
+        </el-form-item>
+        <el-form-item label="绫诲瀷" prop="operationType">
+          <el-select style="width: 100%" v-model="form.operationType" placeholder="璇烽�夋嫨绫诲瀷">
+            <el-option
+              v-for="dict in dict.type.operation_type"
+              :key="dict.value"
+              :label="dict.label"
+              :value="dict.value"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="鎺掑簭" prop="stepSort">
+          <el-input v-model="form.stepSort" placeholder="璇疯緭鍏ユ帓搴�" />
+        </el-form-item>
+        <el-form-item label="鍙傛暟缂栫爜" prop="paramCode">
+          <el-input v-model="form.paramCode" placeholder="璇疯緭鍏ュ弬鏁扮紪鐮�" />
+        </el-form-item>
+        <el-form-item label="鐗╂枡缂栫爜" prop="materialCode">
+          <el-input v-model="form.materialCode" placeholder="璇疯緭鍏ョ墿鏂欑紪鐮�" />
+        </el-form-item>
+<!--        <el-form-item label="閰嶆柟缂栫爜" prop="formulaCode">-->
+<!--          <el-input v-model="form.formulaCode" placeholder="璇疯緭鍏ラ厤鏂圭紪鐮�" />-->
+<!--        </el-form-item>-->
+        <el-form-item label="鍥剧墖" prop="picture">
+          <el-input v-model="form.picture" placeholder="璇疯緭鍏ュ浘鐗�" />
+        </el-form-item>
+        <el-form-item label="澶囨敞" prop="remarks">
+          <el-input v-model="form.remarks" placeholder="璇疯緭鍏ュ娉�" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listFormula} from "@/api/main/bs/formula/formula";
+import { listFormulaChild, getFormulaChild, delFormulaChild, addFormulaChild, updateFormulaChild } from "@/api/main/bs/formulaChild/formulaChild";
+
+export default {
+  name: "FormulaChild",
+  dicts: ['operation_type'],
+  data() {
+    return {
+      pjtUrl: process.env.VUE_APP_BASE_API,
+      headerInformationData:{
+        formulaCode: "",
+        formulaName: "",
+        productCode: "",
+        productName: ""
+      },
+      // 閬僵灞�
+      loading: true,
+      titleName: "",
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      formulaCode:  "",
+      // 閰嶆柟閰嶇疆瀛愪俊鎭〃鏍兼暟鎹�
+      formulaChildList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        workshopCode: null,
+        lineCode: null,
+        processesCode: null,
+        productCode: null,
+        operationType: null,
+        formulaCode: null,
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        id: [
+          { required: true, message: "id涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+      }
+    };
+  },
+  created() {
+    let formulaCode = this.$route.query.formulaCode;
+    this.queryParams.formulaCode = formulaCode;
+    this.formulaCode = formulaCode;
+    this.headerInformation();
+    this.getList();
+  },
+  methods: {
+    /** 宸ヨ壓娴佺▼琛ㄥご淇℃伅 */
+    headerInformation() {
+      listFormula(this.queryParams).then(response => {
+        this.headerInformationData = response.rows[0];
+      });
+    },
+    /** 杩斿洖鎸夐挳鎿嶄綔 */
+    handleClose() {
+      const obj = { path: "/main/pm/formula" };
+      this.$tab.closeOpenPage(obj);
+    },
+    /** 鏌ヨ閰嶆柟閰嶇疆瀛愪俊鎭垪琛� */
+    getList() {
+      this.loading = true;
+      listFormulaChild(this.queryParams).then(response => {
+        this.formulaChildList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        id: null,
+        workshopCode: null,
+        lineCode: null,
+        processesCode: null,
+        productCode: null,
+        operationSteps: null,
+        techRequirement: null,
+        operationType: null,
+        stepSort: null,
+        paramCode: null,
+        materialCode: null,
+        formulaCode: null,
+        picture: null,
+        remarks: null,
+        createUser: null,
+        createTime: null,
+        updateUser: null,
+        updateTime: null,
+        spareField1: null,
+        spareField2: null,
+        spareField3: null,
+        spareField4: null
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.titleName = "娣诲姞閰嶆柟閰嶇疆瀛愪俊鎭�";
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getFormulaChild(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.titleName = "淇敼閰嶆柟閰嶇疆瀛愪俊鎭�";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm() {
+      this.form.formulaCode = this.formulaCode;
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateFormulaChild(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addFormulaChild(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎閰嶆柟閰嶇疆瀛愪俊鎭紪鍙蜂负"' + ids + '"鐨勬暟鎹」锛�').then(function() {
+        return delFormulaChild(ids);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('bs/formulaChild/export', {
+        ...this.queryParams
+      }, `formulaChild_${new Date().getTime()}.xlsx`)
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/main/bs/lineInfo/index.vue b/jcdm-ui/src/views/main/bs/lineInfo/index.vue
new file mode 100644
index 0000000..144732a
--- /dev/null
+++ b/jcdm-ui/src/views/main/bs/lineInfo/index.vue
@@ -0,0 +1,413 @@
+<template>
+  <div class="app-container">
+    <el-card class="box-card">
+      <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+        <el-form-item label="浜х嚎缂栧彿" prop="lineCode">
+          <el-input
+            v-model="queryParams.lineCode"
+            placeholder="璇疯緭鍏ヤ骇绾跨紪鍙�"
+            clearable
+            @keyup.enter.native="handleQuery"
+          />
+        </el-form-item>
+        <el-form-item label="浜х嚎鍚嶇О" prop="lineName">
+          <el-input
+            v-model="queryParams.lineName"
+            placeholder="璇疯緭鍏ヤ骇绾垮悕绉�"
+            clearable
+            @keyup.enter.native="handleQuery"
+          />
+        </el-form-item>
+        <el-form-item label="杞﹂棿缂栧彿" prop="workshopCode">
+          <el-input
+            v-model="queryParams.workshopCode"
+            placeholder="璇疯緭鍏ヨ溅闂寸紪鍙�"
+            clearable
+            @keyup.enter.native="handleQuery"
+          />
+        </el-form-item>
+        <el-form-item style="float: right">
+          <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+<!--          <el-button type="warning" icon="el-icon-copy-document" size="mini" @click="advancedQuery">楂樼骇鏌ヨ</el-button>-->
+          <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+        </el-form-item>
+      </el-form>
+      <el-form :model="queryParams" ref="queryParams" size="small" :inline="true" v-show="advancedShowSearch" label-width="68px"/>
+    </el-card>
+
+    <el-card style="margin-top: 10px" class="box-card">
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['bs:lineInfo:add']"
+        >鏂板</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['bs:lineInfo:edit']"
+        >淇敼</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['bs:lineInfo:remove']"
+        >鍒犻櫎</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['bs:lineInfo:export']"
+        >瀵煎嚭</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+      <el-table v-loading="loading" border :data="lineInfoList" @selection-change="handleSelectionChange" v-if="lineInfoList.length > 0">
+        <el-table-column type="selection" width="55" align="center" />
+        <el-table-column label="浜х嚎缂栧彿" width="120" align="center" prop="lineCode">
+        </el-table-column>
+        <el-table-column :show-overflow-tooltip='true' label="浜х嚎鍚嶇О" align="center" prop="lineName">
+      </el-table-column>
+        <el-table-column label="杞﹂棿缂栫爜" width="120" align="center" prop="workshopCode">
+        </el-table-column>
+        <el-table-column label="杞﹂棿鍚嶇О" width="120" align="center" prop="workshopName">
+        </el-table-column>
+        <el-table-column label="鐘舵��" align="center" prop="status" width="80">
+          <template slot-scope="scope">
+            <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
+          </template>
+        </el-table-column>
+        <el-table-column label="澶囨敞" width="150" align="center" prop="remarks">
+        </el-table-column>
+        <el-table-column label="鍒涘缓浜�" align="center" prop="createUser" width="150">
+        </el-table-column>
+        <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="170">
+        </el-table-column>
+        <el-table-column label="鏇存柊浜�" align="center" prop="updateUser" width="150">
+        </el-table-column>
+        <el-table-column label="鏇存柊鏃堕棿" align="center" prop="updateTime" width="170">
+        </el-table-column>
+        <el-table-column fixed="right" label="鎿嶄綔" width="200" align="center" class-name="small-padding fixed-width">
+          <template slot-scope="scope">
+            <el-button
+              size="mini"
+              type="success"
+              plain
+              style="width: 72px"
+              icon="el-icon-edit"
+              @click="handleUpdate(scope.row)"
+              v-hasPermi="['bs:lineInfo:edit']"
+            >淇敼</el-button>
+            <el-button
+              size="mini"
+              plain
+              style="width: 72px"
+              type="danger"
+              icon="el-icon-delete"
+              @click="handleDelete(scope.row)"
+              v-hasPermi="['bs:lineInfo:remove']"
+            >鍒犻櫎</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <el-empty v-else>
+        <span slot="description">鏆傛棤鏁版嵁</span>
+      </el-empty>
+    </el-card>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+<!--    <el-table v-loading="loading" :data="lineInfoList" @selection-change="handleSelectionChange">-->
+<!--      <el-table-column type="selection" width="55" align="center" />-->
+<!--      <el-table-column label="涓婚敭id" align="center" prop="id" />-->
+<!--      <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">-->
+<!--        <template slot-scope="scope">-->
+<!--          <el-button-->
+<!--            size="mini"-->
+<!--            type="text"-->
+<!--            icon="el-icon-edit"-->
+<!--            @click="handleUpdate(scope.row)"-->
+<!--            v-hasPermi="['main:lineInfo:edit']"-->
+<!--          >淇敼</el-button>-->
+<!--          <el-button-->
+<!--            size="mini"-->
+<!--            type="text"-->
+<!--            icon="el-icon-delete"-->
+<!--            @click="handleDelete(scope.row)"-->
+<!--            v-hasPermi="['main:lineInfo:remove']"-->
+<!--          >鍒犻櫎</el-button>-->
+<!--        </template>-->
+<!--      </el-table-column>-->
+<!--    </el-table>-->
+
+
+
+    <!-- 娣诲姞鎴栦慨鏀逛骇绾夸俊鎭璇濇 -->
+    <el-dialog v-dialogpop-up :title="title" :visible.sync="open" width="500px" append-to-body>
+      <span slot="title">
+        <i class="el-icon-s-order"></i>
+        {{titleName}}
+      </span>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="浜х嚎缂栧彿" prop="lineCode">
+          <el-input v-model="form.lineCode" placeholder="璇疯緭鍏ヤ骇绾跨紪鍙�" />
+        </el-form-item>
+        <el-form-item label="浜х嚎鍚嶇О" prop="lineName">
+          <el-input v-model="form.lineName" placeholder="璇疯緭鍏ヤ骇绾垮悕绉�" />
+        </el-form-item>
+        <el-form-item label="杞﹂棿缂栧彿" prop="workshopCode">
+          <el-select style="width: 100%" @change="handleSelectChange(form.workshopCode)" v-model="form.workshopCode" placeholder="璇烽�夋嫨杞﹂棿缂栧彿">
+            <el-option
+              v-for="item in options"
+              :key="item.workshopCode"
+              :label="item.workshopCode"
+              :value="item.workshopCode">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="杞﹂棿鍚嶇О" prop="workshopName">
+          <el-input disabled v-model="form.workshopName" placeholder="璇疯緭鍏ヨ溅闂村悕绉�" />
+        </el-form-item>
+        <el-form-item label="鐘舵��" prop="status">
+          <el-radio-group v-model="form.status">
+            <el-radio
+              v-for="dict in dict.type.sys_normal_disable"
+              :key="dict.value"
+              :label="dict.value"
+            >{{dict.label}}</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="澶囨敞" prop="remarks">
+          <el-input v-model="form.remarks" placeholder="璇疯緭鍏ュ娉�" />
+        </el-form-item>
+
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listLineInfo, getLineInfo, delLineInfo, addLineInfo, updateLineInfo } from "@/api/main/bs/lineInfo/lineInfo";
+import {listWorkshop} from "@/api/main/bs/workshop/workshop";
+
+export default {
+  name: "LineInfo",
+  dicts: ['sys_normal_disable'],
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      options: [],
+      titleName: 'test',
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 浜х嚎淇℃伅琛ㄦ牸鏁版嵁
+      lineInfoList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      advancedShowSearch: false,
+      // 鏌ヨ鍙傛暟
+
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        lineCode: null,
+        lineName: null,
+        workshopCode: null,
+        workCalendar: null,
+      },
+      workshopCodeQueryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        workshopCode: null,
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+
+        id: [
+          { required: true, message: "涓婚敭id涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        lineCode: [
+          { required: true, message: "浜х嚎缂栧彿涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        lineName: [
+          { required: true, message: "浜х嚎鍚嶇О涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        workshopCode: [
+          { required: true, message: "杞﹂棿缂栧彿涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        workshopName: [
+          { required: true, message: "杞﹂棿鍚嶇О涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+      }
+    };
+  },
+  created() {
+    this.getList();
+    this.initWorkshop();
+  },
+  methods: {
+    // 鍦ㄨ繖閲岀紪鍐欏鐞嗛�変腑浜嬩欢鐨勯�昏緫
+    handleSelectChange(selectedOption) {
+      this.workshopCodeQueryParams.workshopCode = selectedOption;
+      listWorkshop(this.workshopCodeQueryParams).then(response => {
+        this.form.workshopName = response.rows[0].workshopName;
+      });
+    },
+    initWorkshop(){
+      listWorkshop(this.queryParams).then(response => {
+        this.options = response.rows;
+      });
+    },
+    advancedQuery(){
+      this.advancedShowSearch = (this.advancedShowSearch) ? this.advancedShowSearch = false : this.advancedShowSearch = true;
+    },
+    /** 鏌ヨ浜х嚎淇℃伅鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listLineInfo(this.queryParams).then(response => {
+        this.lineInfoList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        id: null,
+        lineCode: null,
+        lineName: null,
+        workshopName: null,
+        workshopCode: null,
+        workCalendar: null,
+        spareField1: null,
+        spareField2: null,
+        remarks: null,
+        createUser: null,
+        createTime: null,
+        updateUser: null,
+        status: "0",
+        updateTime: null
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.initWorkshop();
+      this.titleName = "娣诲姞浜х嚎淇℃伅";
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.reset();
+      this.initWorkshop();
+      const id = row.id || this.ids
+      getLineInfo(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.titleName = "淇敼浜х嚎淇℃伅";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateLineInfo(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addLineInfo(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎浜х嚎缂栧彿涓�"' + ids + '"鐨勬暟鎹」锛�').then(function() {
+        return delLineInfo(ids);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('main/lineInfo/export', {
+        ...this.queryParams
+      }, `lineInfo_${new Date().getTime()}.xlsx`)
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/main/bs/material/index.vue b/jcdm-ui/src/views/main/bs/material/index.vue
new file mode 100644
index 0000000..b295e47
--- /dev/null
+++ b/jcdm-ui/src/views/main/bs/material/index.vue
@@ -0,0 +1,413 @@
+<template>
+  <div class="app-container">
+    <el-card class ="box-card">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="鐗╂枡缂栧彿" prop="materialCode">
+        <el-input
+          v-model="queryParams.materialCode"
+          placeholder="璇疯緭鍏ョ墿鏂欑紪鍙�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="鐗╂枡鍚嶇О" prop="materialName">
+        <el-input
+          v-model="queryParams.materialName"
+          placeholder="璇疯緭鍏ョ墿鏂欏悕绉�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="鐘舵��" prop="status">
+        <el-select v-model="queryParams.status" placeholder="璇烽�夋嫨鐘舵��" clearable>
+          <el-option
+            v-for="dict in dict.type.sys_normal_disable"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item style="float: right">
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+    </el-card>
+    <el-card style="margin-top: 10px" class="box-card">
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['bs:material:add']"
+        >鏂板</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['bs:material:edit']"
+        >淇敼</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['bs:material:remove']"
+        >鍒犻櫎</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['bs:material:export']"
+        >瀵煎嚭</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" border :data="materialList" @selection-change="handleSelectionChange" v-if="materialList.length > 0">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="鐗╂枡缂栧彿"  align="center" prop="materialCode" width="180">
+      </el-table-column>
+      <el-table-column label="鐗╂枡鍚嶇О" align="center" prop="materialName" width="250">
+      </el-table-column>
+      <el-table-column label="鍨嬪彿" align="center" prop="typeZ" width="180">
+      </el-table-column>
+<!--      <el-table-column label="瑙嗗浘" align="center" prop="materialView" width="180">
+      </el-table-column>-->
+      <el-table-column label="绫诲瀷" align="center" prop="typeL">
+        <template slot-scope="scope">
+          <dict-tag :options="dict.type.material_type" :value="scope.row.typeL"/>
+        </template>
+      </el-table-column>
+
+
+
+      <el-table-column label="鍗曚綅" align="center" prop="unit" width="80">
+        <template slot-scope="scope">
+          <dict-tag :options="dict.type.unit" :value="scope.row.unit"/>
+        </template>
+      </el-table-column>
+<!--      <el-table-column label="ERP瑙勬牸" align="center" prop="erpSpec">-->
+<!--      </el-table-column>-->
+
+      <el-table-column label="鐘舵��" align="center" prop="status" width="80">
+        <template slot-scope="scope">
+          <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
+        </template>
+      </el-table-column>
+
+<!--      <el-table-column label="鍘傚晢" align="center" prop="supplier">
+      </el-table-column>-->
+      <el-table-column label="澶囨敞" align="center" prop="remarks" width="180">
+      </el-table-column>
+      <el-table-column label="鍒涘缓浜�" align="center" prop="createUser" width="150">
+      </el-table-column>
+      <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="170">
+      </el-table-column>
+      <el-table-column label="鏇存柊浜�" align="center" prop="updateUser" width="150">
+      </el-table-column>
+      <el-table-column label="鏇存柊鏃堕棿" align="center" prop="updateTime" width="170">
+      </el-table-column>
+      <el-table-column label="鏁版嵁鏉ユ簮" align="center" prop="dataSource">
+      </el-table-column>
+      <el-table-column fixed="right" label="鎿嶄綔" width="200" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="success"
+            plain
+            style="width: 72px"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['bs:material:edit']"
+          >淇敼</el-button>
+          <el-button
+            size="mini"
+            plain
+            style="width: 72px"
+            type="danger"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['bs:material:remove']"
+          >鍒犻櫎</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+      <el-empty v-else>
+        <span slot="description">鏆傛棤鏁版嵁</span>
+      </el-empty>
+    </el-card>
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 娣诲姞鎴栦慨鏀圭墿鏂欎俊鎭璇濇 -->
+    <el-dialog v-dialogpop-up :title="title" :visible.sync="open" width="700px" append-to-body>
+      <span slot="title">
+        <i class="el-icon-s-order"></i>
+        {{titleName}}
+      </span>
+      <el-form ref="form" inline :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="鐗╂枡缂栧彿" prop="materialCode">
+          <el-input v-model="form.materialCode" placeholder="璇疯緭鍏ョ墿鏂欑紪鍙�" />
+        </el-form-item>
+        <el-form-item label="鐗╂枡鍚嶇О" prop="materialName">
+          <el-input v-model="form.materialName" placeholder="璇疯緭鍏ョ墿鏂欏悕绉�" />
+        </el-form-item>
+        <el-form-item label="鐗╂枡绫诲瀷" prop="typeL">
+          <!--          <el-input v-model="form.typeL" placeholder="璇疯緭鍏ョ被鍨�" />-->
+          <el-select v-model="form.typeL" style="width: 204px;" placeholder="璇烽�夋嫨鍗曚綅" clearable>
+            <el-option
+              v-for="dict in dict.type.material_type"
+              :key="dict.value"
+              :label="dict.label"
+              :value="dict.value"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="鐗╂枡鍨嬪彿" prop="typeZ">
+          <el-input v-model="form.typeZ" placeholder="璇疯緭鍏ョ绫�" />
+        </el-form-item>
+<!--        <el-form-item label="瑙嗗浘" prop="materialView">
+          <el-input v-model="form.materialView" placeholder="璇疯緭鍏ヨ鍥�" />
+        </el-form-item>-->
+        <el-form-item label="鍗曚綅" prop="unit">
+<!--          <el-input v-model="form.unit" placeholder="璇疯緭鍏ュ崟浣�" />-->
+          <el-select v-model="form.unit" style="width: 204px;" placeholder="璇烽�夋嫨鍗曚綅" clearable>
+            <el-option
+              v-for="dict in dict.type.unit"
+              :key="dict.value"
+              :label="dict.label"
+              :value="dict.value"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="澶囨敞" prop="remarks">
+          <el-input v-model="form.remarks" placeholder="璇疯緭鍏ュ娉�" />
+        </el-form-item>
+<!--        <el-form-item label="ERP瑙勬牸" prop="erpSpec">
+          <el-input v-model="form.erpSpec" placeholder="璇疯緭鍏RP瑙勬牸" />
+        </el-form-item>-->
+<!--        <el-form-item label="鍘傚晢" prop="supplier">
+          <el-input v-model="form.supplier" placeholder="璇疯緭鍏ュ巶鍟�" />
+        </el-form-item>-->
+        <el-form-item label="鐘舵��" prop="status">
+          <el-radio-group v-model="form.status">
+            <el-radio
+              v-for="dict in dict.type.sys_normal_disable"
+              :key="dict.value"
+              :label="dict.value"
+            >{{dict.label}}</el-radio>
+          </el-radio-group>
+        </el-form-item>
+
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listMaterial, getMaterial, delMaterial, addMaterial, updateMaterial } from "@/api/main/bs/material/material";
+
+export default {
+  name: "Material",
+  dicts: ['sys_normal_disable','unit','material_type'],
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      titleName: 'test',
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 鐗╂枡淇℃伅琛ㄦ牸鏁版嵁
+      materialList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        materialCode: null,
+        materialName: null,
+        materialView: null,
+        typeZ: null,
+        typeL: null,
+        unit: null,
+        matterVersion: null,
+        remarks: null,
+        createUser: null,
+        createTime: null,
+        updateUser: null,
+        erpSpec: null,
+        dataSource: null,
+        version: null,
+        status: null,
+        supplier: null
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        id: [
+          { required: true, message: "涓婚敭id涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        materialCode: [
+          { required: true, message: "鐗╂枡缂栫爜涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        materialName: [
+          { required: true, message: "鐗╂枡鍚嶇О涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        typeL: [
+          { required: true, message: "绫诲瀷涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 鏌ヨ鐗╂枡淇℃伅鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listMaterial(this.queryParams).then(response => {
+        this.materialList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        id: null,
+        materialCode: null,
+        materialName: null,
+        materialView: null,
+        typeZ: null,
+        typeL: null,
+        unit: null,
+        matterVersion: null,
+        remarks: null,
+        createUser: null,
+        createTime: null,
+        updateUser: null,
+        updateTime: null,
+        erpSpec: null,
+        dataSource: null,
+        version: null,
+        status: '0',
+        supplier: null
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.titleName = "娣诲姞鐗╂枡淇℃伅";
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getMaterial(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.titleName = "淇敼鐗╂枡淇℃伅";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateMaterial(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addMaterial(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎鐗╂枡淇℃伅缂栧彿涓�"' + ids + '"鐨勬暟鎹」锛�').then(function() {
+        return delMaterial(ids);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('bs/material/export', {
+        ...this.queryParams
+      }, `material_${new Date().getTime()}.xlsx`)
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/main/bs/processFile/index.vue b/jcdm-ui/src/views/main/bs/processFile/index.vue
new file mode 100644
index 0000000..a1b860d
--- /dev/null
+++ b/jcdm-ui/src/views/main/bs/processFile/index.vue
@@ -0,0 +1,506 @@
+<template>
+  <div class="app-container">
+    <el-card class="box-card">
+        <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+          <el-form-item label="鏂囦欢缂栧彿" prop="fileCode">
+            <el-input
+              v-model="queryParams.fileCode"
+              placeholder="璇疯緭鍏ユ枃浠剁紪鍙�"
+              clearable
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item label="鏂囦欢鍚嶇О" prop="fileName">
+            <el-input
+              v-model="queryParams.fileName"
+              placeholder="璇疯緭鍏ユ枃浠跺悕绉�"
+              clearable
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item label="鏂囦欢鍦板潃" prop="fileAddress">
+            <el-input
+              v-model="queryParams.fileAddress"
+              placeholder="璇疯緭鍏ユ枃浠跺湴鍧�"
+              clearable
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item style="float: right">
+            <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+<!--            <el-button type="warning" icon="el-icon-copy-document" size="mini" @click="advancedQuery">楂樼骇鏌ヨ</el-button>-->
+            <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+          </el-form-item>
+          <el-form :model="queryParams" ref="queryParams" size="small" :inline="true" v-show="advancedShowSearch" label-width="68px">
+          </el-form>
+        </el-form>
+    </el-card>
+
+    <el-card style="margin-top: 10px" class="box-card">
+        <el-row :gutter="10" class="mb8">
+          <el-col :span="1.5">
+            <el-button
+              type="primary"
+              plain
+              icon="el-icon-plus"
+              size="mini"
+              @click="handleAdd"
+              v-hasPermi="['bs:processFile:add']"
+            >鏂板</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="success"
+              plain
+              icon="el-icon-edit"
+              size="mini"
+              :disabled="single"
+              @click="handleUpdate"
+              v-hasPermi="['bs:processFile:edit']"
+            >淇敼</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="danger"
+              plain
+              icon="el-icon-delete"
+              size="mini"
+              :disabled="multiple"
+              @click="handleDelete"
+              v-hasPermi="['bs:processFile:remove']"
+            >鍒犻櫎</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="warning"
+              plain
+              icon="el-icon-download"
+              size="mini"
+              @click="handleExport"
+              v-hasPermi="['bs:processFile:export']"
+            >瀵煎嚭</el-button>
+          </el-col>
+          <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+        </el-row>
+        <el-table border v-loading="loading" :data="processFileList" @selection-change="handleSelectionChange" v-if="processFileList.length > 0">
+          <el-table-column type="selection" width="55" align="center" />
+          <el-table-column label="浜у搧缂栧彿" align="center" prop="productCode">
+          </el-table-column>
+          <el-table-column label="浜у搧鍚嶇О" align="center" prop="productName">
+          </el-table-column>
+          <el-table-column label="宸ュ簭缂栧彿" align="center" prop="processesCode">
+          </el-table-column>
+          <el-table-column label="宸ュ簭鍚嶇О" align="center" prop="processesName">
+          </el-table-column>
+          <el-table-column label="鏂囦欢缂栧彿" align="center" prop="fileCode">
+          </el-table-column>
+          <el-table-column label="鏂囦欢鍚嶇О" align="center" prop="fileName">
+          </el-table-column>
+          <el-table-column :show-overflow-tooltip='true' width="150" label="鏂囦欢鍦板潃" align="center" prop="fileAddress">
+            <template slot-scope="scope">
+              <a :href="scope.row.fileAddress" target="_blank" style="color: #00afff" class="buttonText">{{scope.row.fileAddress}}</a>
+            </template>
+          </el-table-column>
+          <el-table-column label="鐘舵��" align="center" prop="status">
+            <template slot-scope="scope">
+              <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
+            </template>
+          </el-table-column>
+<!--          <el-table-column label="鍒涘缓浜�" align="center" prop="createUser">-->
+<!--          </el-table-column>-->
+<!--          <el-table-column label="鏇存柊浜�" align="center" prop="updateUser">-->
+<!--          </el-table-column>-->
+          <el-table-column label="澶囨敞" align="center" prop="remarks">
+          </el-table-column>
+          <el-table-column fixed="right" width="300" label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+            <template slot-scope="scope">
+              <el-button
+                size="mini"
+                type="success"
+                plain
+                style="width: 72px"
+                icon="el-icon-edit"
+                @click="handleUpdate(scope.row)"
+                v-hasPermi="['bs:processFile:edit']"
+              >淇敼</el-button>
+              <el-button
+                size="mini"
+                type="danger"
+                plain
+                style="width: 72px"
+                icon="el-icon-delete"
+                @click="handleDelete(scope.row)"
+                v-hasPermi="['bs:processFile:remove']"
+              >鍒犻櫎</el-button>
+              <el-button
+                size="mini"
+                plain
+                type="warning"
+                style="width: 72px"
+                icon="el-icon-download"
+                @click="handleDownload(scope.row)"
+              >涓嬭浇</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+      <el-empty v-else>
+        <span slot="description">鏆傛棤鏁版嵁</span>
+      </el-empty>
+    </el-card>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 娣诲姞鎴栦慨鏀瑰伐鑹烘枃妗e璇濇 -->
+    <el-dialog v-dialogpop-up :title="title" :visible.sync="open" width="500px" append-to-body>
+      <span slot="title">
+        <i class="el-icon-s-order"></i>
+        {{titleName}}
+      </span>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="浜у搧缂栧彿" prop="productCode">
+          <el-input v-model="form.productCode" placeholder="璇烽�夋嫨浜у搧" >
+            <el-button slot="append" @click="handleSelectProduct" icon="el-icon-search"></el-button>
+          </el-input>
+          <ItemSelect ref="itemSelect" @onSelected="onItemSelected" > </ItemSelect>
+        </el-form-item>
+        <el-form-item label="浜у搧鍚嶇О" prop="productName">
+          <el-input  disabled v-model="form.productName" placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�" />
+        </el-form-item>
+        <el-form-item label="宸ュ簭缂栧彿" prop="processesCode">
+          <el-select style="width: 100%" @change="handleSelectChangeprocessesCode(form.processesCode)" v-model="form.processesCode" placeholder="璇烽�夋嫨宸ュ簭缂栧彿">
+            <el-option
+              v-for="item in options"
+              :key="item.index"
+              :label="item.processesName"
+              :value="item.processesCode">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="宸ュ簭鍚嶇О" prop="processesName">
+          <el-input  disabled v-model="form.processesName" placeholder="璇疯緭鍏ュ伐搴忓悕绉�" />
+        </el-form-item>
+<!--        <el-form-item label="鏂囦欢缂栧彿" prop="fileCode">-->
+<!--          <el-input v-model="form.fileCode" placeholder="璇疯緭鍏ユ枃浠剁紪鍙�" />-->
+<!--        </el-form-item>-->
+        <el-form-item label="鏂囦欢鍚嶇О"  prop="fileName">
+          <el-input v-model="form.fileName" disabled placeholder="璇疯緭鍏ユ枃浠跺悕绉�" />
+        </el-form-item>
+        <el-form-item label="鏂囦欢鍦板潃" prop="fileAddress">
+<!--          <el-input v-model="form.fileAddress" placeholder="璇疯緭鍏ユ枃浠跺湴鍧�" />-->
+          <el-upload
+            ref="upload"
+            :limit="1"
+            accept=".doc, .docx"
+            :action="upload.url"
+            :headers="upload.headers"
+            :on-remove="removes"
+            :file-list="upload.fileList"
+            :on-progress="handleFileUploadProgress"
+            :on-success="handleFileSuccess"
+            :auto-upload="false">
+            <el-button slot="trigger" size="small" type="primary">閫夊彇鏂囦欢</el-button>
+            <el-button style="margin-left: 10px;" size="small" type="success" :loading="upload.isUploading" @click="submitUpload">涓婁紶鍒版湇鍔″櫒</el-button>
+            <div slot="tip" class="el-upload__tip">鍙兘涓婁紶doc/docx鏂囦欢锛屼笖涓嶈秴杩�10MB</div>
+          </el-upload>
+        </el-form-item>
+
+        <el-form-item label="鐘舵��" prop="status">
+          <el-radio-group v-model="form.status">
+            <el-radio
+              v-for="dict in dict.type.sys_normal_disable"
+              :key="dict.value"
+              :label="dict.value"
+            >{{dict.label}}</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="澶囨敞" prop="remarks">
+          <el-input v-model="form.remarks" placeholder="璇疯緭鍏ュ娉�" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { getToken } from "@/utils/auth";
+import { listProcessFile, getProcessFile, delProcessFile, addProcessFile, updateProcessFile } from "@/api/main/bs/processFile/processFile";
+import {listProductBom} from "@/api/main/bs/ProductBom/ProductBom";
+import {listProcesses} from "@/api/main/bs/processes/processes";
+import ItemSelect from "@/components/itemSelect/single.vue";
+import {listTechnologyRoute} from "@/api/main/bs/technologyRoute/technologyRoute";
+
+
+export default {
+  name: "ProcessFile",
+  components: {ItemSelect},
+  dicts: ['sys_normal_disable'],
+  data() {
+    return {
+      // 涓婁紶鍙傛暟
+      upload: {
+        // 鏄惁绂佺敤涓婁紶
+        isUploading: false,
+        // 璁剧疆涓婁紶鐨勮姹傚ご閮�
+        headers: { Authorization: "Bearer " + getToken() },
+        // 涓婁紶鐨勫湴鍧�
+        url: process.env.VUE_APP_BASE_API + "/common/upload",
+        // 涓婁紶鐨勬枃浠跺垪琛�
+        fileList: []
+      },
+      // 閬僵灞�
+      loading: true,
+      titleName: "",
+      // 閫変腑鏁扮粍
+      ids: [],
+      options: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 宸ヨ壓鏂囨。琛ㄦ牸鏁版嵁
+      processFileList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      advancedShowSearch: false,
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        productCode: null,
+        productName: null,
+        processesCode: null,
+        processesName: null,
+        fileCode: null,
+        fileName: null,
+        fileAddress: null,
+        status: null,
+        createUser: null,
+        updateUser: null,
+        remarks: null
+      },
+      productCodeQueryParams:{
+        pageNum: 1,
+        pageSize: 10,
+        productCode: null,
+      },
+      processesCodeQueryParams:{
+        pageNum: 1,
+        pageSize: 10,
+        processesCodes: null,
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        id: [
+          { required: true, message: "id涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        productCode: [
+          { required: true, message: "浜у搧缂栧彿涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        processesCode: [
+          { required: true, message: "宸ュ簭缂栧彿涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+      }
+    };
+  },
+  created() {
+    this.getList();
+    this.initProcesses();
+  },
+  methods: {
+    // 鏂囦欢涓嬭浇澶勭悊
+    handleDownload(row) {
+      var name = row.fileName;
+      var url = row.fileAddress;
+      var suffix = url.substring(url.lastIndexOf("."), url.length);
+      const a = document.createElement('a')
+      a.setAttribute('download', name + suffix)
+      a.setAttribute('target', '_blank')
+      a.setAttribute('href', url)
+      a.click()
+    },
+    // 鏂囦欢鎻愪氦澶勭悊
+    submitUpload() {
+      this.$refs.upload.submit();
+    },
+    // 鏂囦欢涓婁紶涓鐞�
+    handleFileUploadProgress(event, file, fileList) {
+      this.upload.isUploading = true;
+    },
+    // 鏂囦欢涓婁紶鎴愬姛澶勭悊
+    handleFileSuccess(response, file, fileList) {
+      console.log(response)
+      this.upload.isUploading = false;
+      this.form.fileAddress = response.url;
+      this.form.fileName = response.originalFilename;
+      this.$modal.msgSuccess(response.msg);
+    },
+    handleSelectChangeprocessesCode(selectedOption) {
+      this.processesCodeQueryParams.processesCodes = selectedOption;
+      listProcesses(this.queryParams).then(response => {
+        this.form.processesName = response.rows[0].processesName;
+      });
+    },
+    initProcesses(){
+      listProcesses(this.queryParams).then(response => {
+        this.options = response.rows;
+      });
+    },
+    //鐗╂枡閫夋嫨寮瑰嚭妗�
+    onItemSelected(obj){
+      if(obj !== undefined && obj !== null){
+        let productCode = obj.materialCode;
+        this.form.productCode = productCode;
+        this.form.productName = obj.materialName;
+        this.queryParams.productCode = productCode
+        listTechnologyRoute(this.queryParams).then(response => {
+          this.form.routeCode = response.rows[0].routeCode;
+        });
+        listProductBom(this.queryParams).then(response => {
+          this.form.bomCode = response.rows[0].bomCode;
+        });
+      }
+    },
+    handleSelectProduct(){
+      this.$refs.itemSelect.showFlag = true;
+    },
+
+    advancedQuery(){
+      this.advancedShowSearch = (this.advancedShowSearch) ? this.advancedShowSearch = false : this.advancedShowSearch = true;
+    },
+    /** 鏌ヨ宸ヨ壓鏂囨。鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listProcessFile(this.queryParams).then(response => {
+        this.processFileList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        id: null,
+        productCode: null,
+        productName: null,
+        processesCode: null,
+        processesName: null,
+        fileCode: null,
+        fileName: null,
+        fileAddress: null,
+        status: "0",
+        createUser: null,
+        createTime: null,
+        updateUser: null,
+        updateTime: null,
+        spareField1: null,
+        spareField2: null,
+        spareField3: null,
+        spareField4: null,
+        remarks: null
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.upload.fileList = [];
+      this.reset();
+      this.open = true;
+      this.titleName = "娣诲姞宸ヨ壓鏂囨。";
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.upload.fileList = [];
+      if(row.fileAddress !== ""){
+        this.upload.fileList = [{ name: row.fileName, url: row.fileAddress }];
+      }
+      // this.upload.fileList = [{ name: row.fileName, url: row.fileAddress }];
+      this.reset();
+      const id = row.id || this.ids
+      getProcessFile(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.titleName = "淇敼宸ヨ壓鏂囨。";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateProcessFile(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addProcessFile(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    removes(){
+      this.form.fileAddress = '';
+      this.form.fileName = '';
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎宸ヨ壓鏂囨。缂栧彿涓�"' + ids + '"鐨勬暟鎹」锛�').then(function() {
+        return delProcessFile(ids);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('bs/processFile/export', {
+        ...this.queryParams
+      }, `processFile_${new Date().getTime()}.xlsx`)
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/main/bs/processes/index.vue b/jcdm-ui/src/views/main/bs/processes/index.vue
new file mode 100644
index 0000000..f4c2d56
--- /dev/null
+++ b/jcdm-ui/src/views/main/bs/processes/index.vue
@@ -0,0 +1,358 @@
+<template>
+  <div class="app-container">
+    <el-card class="box-card">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="宸ュ簭缂栧彿" prop="processesCode">
+        <el-input
+          v-model="queryParams.processesCode"
+          placeholder="璇疯緭鍏ュ伐搴忕紪鍙�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="宸ュ簭鍚嶇О" prop="processesName">
+        <el-input
+          v-model="queryParams.processesName"
+          placeholder="璇疯緭鍏ュ伐搴忓悕绉�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item style="float: right">
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+      <el-form :model="queryParams" ref="queryParams" size="small" :inline="true" v-show="advancedShowSearch" label-width="68px"/>
+    </el-card>
+
+    <el-card style="margin-top: 10px" class="box-card">
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['bs:processes:add']"
+        >鏂板</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['bs:processes:edit']"
+        >淇敼</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['bs:processes:remove']"
+        >鍒犻櫎</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['bs:processes:export']"
+        >瀵煎嚭</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+    <el-table v-loading="loading" border :data="processesList" @selection-change="handleSelectionChange" v-if="processesList.length > 0">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="宸ュ簭缂栧彿" align="center" prop="processesCode">
+      </el-table-column>
+      <el-table-column label="宸ュ簭鍚嶇О" align="center" prop="processesName">
+      </el-table-column>
+<!--      <el-table-column label="宸ュ簭绫诲瀷" align="center" prop="processesType">-->
+<!--      </el-table-column>-->
+      <el-table-column label="鐘舵��" align="center" prop="status" width="80">
+        <template slot-scope="scope">
+          <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="澶囨敞" align="center" prop="remarks">
+      </el-table-column>
+      <el-table-column label="鍒涘缓浜�" align="center" prop="createUser" width="160">
+      </el-table-column>
+      <el-table-column label="鍒涘缓鏃堕棿" width="160" align="center" prop="createTime">
+      </el-table-column>
+      <el-table-column label="鏇存柊浜�" align="center" prop="updateUser" width="160">
+      </el-table-column>
+      <el-table-column label="鏇存敼鏃堕棿" width="160" align="center" prop="updateTime">
+      </el-table-column>
+
+      <el-table-column fixed="right" label="鎿嶄綔" width="200" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="success"
+            plain
+            style="width: 72px"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['bs:processes:edit']"
+          >淇敼</el-button>
+          <el-button
+            size="mini"
+            plain
+            style="width: 72px"
+            type="danger"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['bs:processes:remove']"
+          >鍒犻櫎</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+      <el-empty v-else>
+        <span slot="description">鏆傛棤鏁版嵁</span>
+      </el-empty>
+    </el-card>
+
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 娣诲姞鎴栦慨鏀瑰伐搴忎俊鎭璇濇 -->
+    <el-dialog v-dialogpop-up :title="title" :visible.sync="open" width="500px" append-to-body>
+      <span slot="title">
+        <i class="el-icon-s-order"></i>
+        {{titleName}}
+      </span>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="宸ュ簭缂栧彿" prop="processesCode">
+          <el-input v-model="form.processesCode" placeholder="璇疯緭鍏ュ伐搴忕紪鍙�" />
+        </el-form-item>
+        <el-form-item label="宸ュ簭鍚嶇О" prop="processesName">
+          <el-input v-model="form.processesName" placeholder="璇疯緭鍏ュ伐搴忓悕绉�" />
+        </el-form-item>
+<!--        <el-form-item label="宸ュ簭绫诲瀷" prop="processesType">-->
+<!--          <el-select v-model="form.processesType" placeholder="璇烽�夋嫨宸ュ簭绫诲瀷">-->
+<!--            <el-option-->
+<!--              v-for="dict in dict.type.${dictType}"-->
+<!--              :key="dict.value"-->
+<!--              :label="dict.label"-->
+<!--              :value="dict.value"-->
+<!--            ></el-option>-->
+<!--          </el-select>-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="鍑嗗鏃堕棿" prop="preparationTime">-->
+<!--          <el-input v-model="form.preparationTime" placeholder="璇疯緭鍏ュ噯澶囨椂闂�" />-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="鐢熶骇鏃堕棿" prop="productiveTime">-->
+<!--          <el-input v-model="form.productiveTime" placeholder="璇疯緭鍏ョ敓浜ф椂闂�" />-->
+<!--        </el-form-item>-->
+        <el-form-item label="鐘舵��" prop="status">
+          <el-radio-group v-model="form.status">
+            <el-radio
+              v-for="dict in dict.type.sys_normal_disable"
+              :key="dict.value"
+              :label="dict.value"
+            >{{dict.label}}</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="澶囨敞" prop="remarks">
+          <el-input v-model="form.remarks" placeholder="璇疯緭鍏ュ娉�" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listProcesses, getProcesses, delProcesses, addProcesses, updateProcesses } from "@/api/main/bs/processes/processes";
+
+export default {
+  name: "Processes",
+  dicts: ['sys_normal_disable'],
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      titleName: 'test',
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 宸ュ簭淇℃伅琛ㄦ牸鏁版嵁
+      processesList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      advancedShowSearch: false,
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        processesCode: null,
+        processesName: null,
+        processesType: null,
+        status: null,
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        id: [
+          { required: true, message: "涓婚敭id涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        processesCode: [
+          { required: true, message: "宸ュ簭缂栧彿涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        processesName: [
+          { required: true, message: "宸ュ簭鍚嶇О涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        processesType: [
+          { required: true, message: "宸ュ簭绫诲瀷涓嶈兘涓虹┖", trigger: "change" }
+        ],
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    advancedQuery(){
+      this.advancedShowSearch = (this.advancedShowSearch) ? this.advancedShowSearch = false : this.advancedShowSearch = true;
+    },
+    /** 鏌ヨ宸ュ簭淇℃伅鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listProcesses(this.queryParams).then(response => {
+        this.processesList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        id: null,
+        processesCode: null,
+        processesName: null,
+        processesType: null,
+        preparationTime: null,
+        productiveTime: null,
+        status: "0",
+        spareField1: null,
+        spareField2: null,
+        spareField3: null,
+        spareField4: null,
+        createUser: null,
+        createTime: null,
+        updateUser: null,
+        updateTime: null,
+        remarks: null
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.queryParams.remarks = null;
+      this.queryParams.createUser = null;
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.titleName = "娣诲姞宸ュ簭淇℃伅";
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getProcesses(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.titleName = "淇敼宸ュ簭淇℃伅";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateProcesses(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addProcesses(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎宸ュ簭淇℃伅缂栧彿涓�"' + ids + '"鐨勬暟鎹」锛�').then(function() {
+        return delProcesses(ids);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('bs/processes/export', {
+        ...this.queryParams
+      }, `processes_${new Date().getTime()}.xlsx`)
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/main/bs/technologyRoute/index.vue b/jcdm-ui/src/views/main/bs/technologyRoute/index.vue
new file mode 100644
index 0000000..12ef123
--- /dev/null
+++ b/jcdm-ui/src/views/main/bs/technologyRoute/index.vue
@@ -0,0 +1,367 @@
+<template>
+  <div class="app-container">
+    <el-card class="box-card">
+      <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+        <el-form-item label-width="120" label="宸ヨ壓娴佺▼缂栫爜" prop="routeCode">
+          <el-input
+            v-model="queryParams.routeCode"
+            placeholder="璇疯緭鍏ュ伐鑹烘祦绋嬬紪鐮�"
+            clearable
+            @keyup.enter.native="handleQuery"
+          />
+        </el-form-item>
+        <el-form-item label="浜у搧缂栫爜" prop="productCode">
+          <el-input
+            v-model="queryParams.productCode"
+            placeholder="璇疯緭鍏ヤ骇鍝佺紪鐮�"
+            clearable
+            @keyup.enter.native="handleQuery"
+          />
+        </el-form-item>
+        <el-form-item label="鐘舵��" prop="status">
+          <el-select v-model="queryParams.status" placeholder="璇烽�夋嫨鐘舵��" clearable>
+            <el-option
+              v-for="dict in dict.type.sys_normal_disable"
+              :key="dict.value"
+              :label="dict.label"
+              :value="dict.value"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item style="float: right">
+          <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+          <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+        </el-form-item>
+      </el-form>
+    </el-card>
+
+    <el-card style="margin-top: 10px" class="box-card">
+      <el-row :gutter="10" class="mb8">
+        <el-col :span="1.5">
+          <el-button
+            type="primary"
+            plain
+            icon="el-icon-plus"
+            size="mini"
+            @click="handleAdd"
+            v-hasPermi="['bs:technologyRoute:add']"
+          >鏂板</el-button>
+        </el-col>
+        <el-col :span="1.5">
+          <el-button
+            type="success"
+            plain
+            icon="el-icon-edit"
+            size="mini"
+            :disabled="single"
+            @click="handleUpdate"
+            v-hasPermi="['bs:technologyRoute:edit']"
+          >淇敼</el-button>
+        </el-col>
+        <el-col :span="1.5">
+          <el-button
+            type="danger"
+            plain
+            icon="el-icon-delete"
+            size="mini"
+            :disabled="multiple"
+            @click="handleDelete"
+            v-hasPermi="['bs:technologyRoute:remove']"
+          >鍒犻櫎</el-button>
+        </el-col>
+        <el-col :span="1.5">
+          <el-button
+            type="warning"
+            plain
+            icon="el-icon-download"
+            size="mini"
+            @click="handleExport"
+            v-hasPermi="['bs:technologyRoute:export']"
+          >瀵煎嚭</el-button>
+        </el-col>
+        <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+      </el-row>
+
+      <el-table border v-loading="loading" :data="technologyRouteList" @selection-change="handleSelectionChange" v-if="technologyRouteList.length > 0">
+        <el-table-column type="selection" width="55" align="center" />
+        <el-table-column :show-overflow-tooltip='true' label="宸ヨ壓娴佺▼缂栫爜" width="130" align="center">
+          <template slot-scope="scope">
+            <router-link :to="{path: '/main/route-data/index/', query: {routeCode: scope.row.routeCode,routeId: scope.row.id} }" class="link-type">
+              <span>{{ scope.row.routeCode }}</span>
+            </router-link>
+          </template>
+        </el-table-column>
+        <el-table-column  :show-overflow-tooltip='true' label="宸ヨ壓娴佺▼鍚嶇О" width="130" align="center" prop="routeName">
+        </el-table-column>
+        <el-table-column label="浜у搧缂栫爜" width="130" align="center" prop="productCode">
+        </el-table-column>
+        <el-table-column label="浜у搧鍚嶇О" width="160" align="center" prop="productName">
+        </el-table-column>
+        <el-table-column label="鐗堟湰" align="center" prop="version">
+        </el-table-column>
+        <el-table-column label="鐘舵��" align="center" prop="status">
+          <template slot-scope="scope">
+            <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
+          </template>
+        </el-table-column>
+        <el-table-column label="鏁版嵁鏉ユ簮" align="center" prop="dataSource">
+        </el-table-column>
+        <el-table-column label="澶囨敞" align="center" prop="remark">
+        </el-table-column>
+        <el-table-column label="鍒涘缓鐢ㄦ埛" width="160" align="center" prop="createUser">
+        </el-table-column>
+        <el-table-column label="鍒涘缓鏃堕棿" width="160" align="center" prop="createTime">
+        </el-table-column>
+        <el-table-column label="鏇存敼鐢ㄦ埛" width="160" align="center" prop="updateUser">
+        </el-table-column>
+        <el-table-column label="鏇存敼鏃堕棿" width="160" align="center" prop="updateTime">
+        </el-table-column>
+        <el-table-column fixed="right" label="鎿嶄綔" width="200" align="center" class-name="small-padding fixed-width">
+          <template slot-scope="scope">
+            <el-button
+              size="mini"
+              type="success"
+              plain
+              style="width: 72px"
+              icon="el-icon-edit"
+              @click="handleUpdate(scope.row)"
+              v-hasPermi="['bs:technologyRoute:edit']"
+            >淇敼</el-button>
+            <el-button
+              size="mini"
+              plain
+              style="width: 72px"
+              type="danger"
+              icon="el-icon-delete"
+              @click="handleDelete(scope.row)"
+              v-hasPermi="['bs:technologyRoute:remove']"
+            >鍒犻櫎</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <el-empty v-else>
+        <span slot="description">鏆傛棤鏁版嵁</span>
+      </el-empty>
+    </el-card>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 娣诲姞鎴栦慨鏀瑰伐鑹烘祦绋嬪璇濇 -->
+    <el-dialog v-dialogpop-up :title="title" :visible.sync="open" width="500px" append-to-body>
+      <span slot="title">
+        <i class="el-icon-s-order"></i>
+        {{titleName}}
+      </span>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="娴佺▼缂栫爜" prop="routeCode">
+          <el-input v-model="form.routeCode" placeholder="璇疯緭鍏ュ伐鑹烘祦绋嬬紪鐮�" />
+        </el-form-item>
+        <el-form-item label="娴佺▼鍚嶇О" prop="routeName">
+          <el-input v-model="form.routeName" placeholder="璇疯緭鍏ュ伐鑹烘祦绋嬪悕绉�" />
+        </el-form-item>
+        <el-form-item label="浜у搧缂栫爜" prop="productCode">
+          <el-input v-model="form.productCode" placeholder="璇疯緭鍏ヤ骇鍝佺紪鐮�" />
+        </el-form-item>
+        <el-form-item label="浜у搧鍚嶇О" prop="productName">
+          <el-input v-model="form.productName" placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�" />
+        </el-form-item>
+        <el-form-item label="鐘舵��" prop="status">
+          <el-radio-group v-model="form.status">
+            <el-radio
+              v-for="dict in dict.type.sys_normal_disable"
+              :key="dict.value"
+              :label="dict.value"
+            >{{dict.label}}</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="鐗堟湰" prop="version">
+          <el-input v-model="form.version" placeholder="璇疯緭鍏ョ増鏈�" />
+        </el-form-item>
+        <el-form-item label="澶囨敞" prop="remark">
+          <el-input v-model="form.remark" placeholder="璇疯緭鍏ュ娉�" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { updateTechnologyRouteAndChild, listTechnologyRoute, getTechnologyRoute, delTechnologyRoute, addTechnologyRoute, updateTechnologyRoute } from "@/api/main/bs/technologyRoute/technologyRoute";
+
+export default {
+  name: "TechnologyRoute",
+  dicts: ['sys_normal_disable'],
+
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      titleName: 'test',
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 宸ヨ壓娴佺▼琛ㄦ牸鏁版嵁
+      technologyRouteList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        routeCode: null,
+        routeName: null,
+        productCode: null,
+        productName: null,
+        status: null,
+        dataSource: null,
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        id: [
+          { required: true, message: "涓婚敭id涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        routeCode: [
+          { required: true, message: "宸ヨ壓娴佺▼缂栫爜涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        productCode: [
+          { required: true, message: "浜у搧缂栫爜涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 鏌ヨ宸ヨ壓娴佺▼鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listTechnologyRoute(this.queryParams).then(response => {
+        console.log(response.rows)
+        this.technologyRouteList = response.rows;
+        console.log(this.technologyRouteList)
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        id: null,
+        routeCode: null,
+        routeName: null,
+        productCode: null,
+        productName: null,
+        version: null,
+        status: "0",
+        dataSource: null,
+        remark: null,
+        createUser: null,
+        createTime: null,
+        updateUser: null,
+        updateTime: null,
+        spareField1: null,
+        spareField2: null,
+        spareField3: null,
+        spareField4: null
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.titleName = "娣诲姞宸ヨ壓娴佺▼";
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getTechnologyRoute(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.titleName = "淇敼宸ヨ壓娴佺▼";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            // updateTechnologyRoute(this.form).then(response => {
+            updateTechnologyRouteAndChild(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addTechnologyRoute(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎宸ヨ壓娴佺▼缂栧彿涓�"' + ids + '"鐨勬暟鎹」锛�').then(function() {
+        return delTechnologyRoute(ids);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('main/technologyRoute/export', {
+        ...this.queryParams
+      }, `technologyRoute_${new Date().getTime()}.xlsx`)
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/main/bs/technologyRouteChild/index.vue b/jcdm-ui/src/views/main/bs/technologyRouteChild/index.vue
new file mode 100644
index 0000000..0a22f6c
--- /dev/null
+++ b/jcdm-ui/src/views/main/bs/technologyRouteChild/index.vue
@@ -0,0 +1,459 @@
+<template>
+  <div class="app-container">
+    <el-card class="box-card">
+      <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+        <el-form-item label="宸ュ簭缂栫爜" prop="processesCode">
+          <el-input
+            v-model="queryParams.processesCode"
+            placeholder="璇疯緭鍏ュ伐搴忕紪鐮�"
+            clearable
+            @keyup.enter.native="handleQuery"
+          />
+        </el-form-item>
+        <el-form-item label="宸ュ簭鍚嶇О" prop="processesName">
+          <el-input
+            v-model="queryParams.processesName"
+            placeholder="璇疯緭鍏ュ伐搴忓悕绉�"
+            clearable
+            @keyup.enter.native="handleQuery"
+          />
+        </el-form-item>
+        <el-form-item label-width="120" label="鏄惁鍏抽敭宸ュ簭" prop="keyProcessesFlag">
+          <el-select v-model="queryParams.keyProcessesFlag" placeholder="璇烽�夋嫨" clearable>
+            <el-option
+              v-for="dict in dict.type.sys_yes_no"
+              :key="dict.value"
+              :label="dict.label"
+              :value="dict.value"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item style="float: right">
+          <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+          <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+        </el-form-item>
+      </el-form>
+    </el-card>
+
+    <el-card style="margin-top: 10px" class="box-card">
+      <el-row :gutter="10" class="mb8">
+        <el-col :span="1.5">
+          <el-button
+            type="primary"
+            plain
+            icon="el-icon-plus"
+            size="mini"
+            @click="handleAdd"
+            v-hasPermi="['bs:technologyRouteChild:add']"
+          >鏂板</el-button>
+        </el-col>
+        <el-col :span="1.5">
+          <el-button
+            type="success"
+            plain
+            icon="el-icon-edit"
+            size="mini"
+            :disabled="single"
+            @click="handleUpdate"
+            v-hasPermi="['bs:technologyRouteChild:edit']"
+          >淇敼</el-button>
+        </el-col>
+        <el-col :span="1.5">
+          <el-button
+            type="danger"
+            plain
+            icon="el-icon-delete"
+            size="mini"
+            :disabled="multiple"
+            @click="handleDelete"
+            v-hasPermi="['bs:technologyRouteChild:remove']"
+          >鍒犻櫎</el-button>
+        </el-col>
+        <el-col :span="1.5">
+          <el-button
+            type="warning"
+            plain
+            icon="el-icon-download"
+            size="mini"
+            @click="handleExport"
+            v-hasPermi="['bs:technologyRouteChild:export']"
+          >瀵煎嚭</el-button>
+        </el-col>
+        <el-col :span="1.5">
+          <el-button
+            type="warning"
+            plain
+            icon="el-icon-close"
+            size="mini"
+            @click="handleClose"
+          >鍏抽棴</el-button>
+        </el-col>
+        <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+      </el-row>
+      <el-descriptions class="margin-top" :column="4" :size="size" border>
+        <el-descriptions-item :span="1">
+          <template slot="label">
+            <i class="el-icon-user"></i>
+            宸ヨ壓娴佺▼缂栫爜
+          </template>
+          {{headerInformationData.routeCode}}
+        </el-descriptions-item>
+        <el-descriptions-item :span="1">
+          <template slot="label">
+            <i class="el-icon-mobile-phone"></i>
+            宸ヨ壓娴佺▼鍚嶇О
+          </template>
+          {{headerInformationData.routeName}}
+        </el-descriptions-item>
+        <el-descriptions-item :span="1">
+          <template slot="label">
+            <i class="el-icon-location-outline"></i>
+            浜у搧缂栫爜
+          </template>
+          {{headerInformationData.productCode}}
+        </el-descriptions-item>
+        <el-descriptions-item :span="1">
+          <template slot="label">
+            <i class="el-icon-tickets"></i>
+            浜у搧鍚嶇О
+          </template>
+          {{headerInformationData.productName}}
+        </el-descriptions-item>
+      </el-descriptions>
+      <el-table v-loading="loading" :width="tableWidth" style="width: auto;" border :data="technologyRouteChildList" @selection-change="handleSelectionChange" v-if="technologyRouteChildList.length > 0">
+        <el-table-column type="selection" width="55" align="center" />
+        <el-table-column label="涓婚敭id" align="center" prop="id" />
+        <el-table-column label="宸ュ簭缂栫爜" align="center" prop="processesCode">
+        </el-table-column>
+        <el-table-column label="宸ュ簭鍚嶇О" align="center" prop="processesName">
+        </el-table-column>
+        <el-table-column label="鍔犲伐椤哄簭" align="center" prop="stepNo">
+        </el-table-column>
+        <el-table-column label="鏄惁鍏抽敭宸ュ簭" align="center" prop="keyProcessesFlag">
+          <template slot-scope="scope">
+            <dict-tag :options="dict.type.sys_yes_no" :value="scope.row.keyProcessesFlag"/>
+          </template>
+        </el-table-column>
+        <el-table-column label="鍒涘缓鐢ㄦ埛" align="center" prop="createUser">
+        </el-table-column>
+        <el-table-column width="160" :show-overflow-tooltip='true' label="鍒涘缓鏃堕棿" align="center" prop="createTime">
+        </el-table-column>
+        <el-table-column label="鏇存敼鐢ㄦ埛" align="center" prop="updateUser">
+        </el-table-column>
+        <el-table-column width="160" :show-overflow-tooltip='true' label="鏇存敼鏃堕棿" align="center" prop="updateTime">
+        </el-table-column>
+        <el-table-column label="澶囨敞" align="center" prop="remark">
+        </el-table-column>
+        <el-table-column width="130" :show-overflow-tooltip='true' label="宸ヨ壓娴佺▼缂栫爜" align="center" prop="routeCode">
+        </el-table-column>
+        <el-table-column fixed="right" label="鎿嶄綔" width="200" align="center" class-name="small-padding fixed-width">
+          <template slot-scope="scope">
+            <el-button
+              size="mini"
+              type="success"
+              plain
+              style="width: 72px"
+              icon="el-icon-edit"
+              @click="handleUpdate(scope.row)"
+              v-hasPermi="['bs:technologyRouteChild:edit']"
+            >淇敼</el-button>
+            <el-button
+              size="mini"
+              plain
+              style="width: 72px"
+              type="danger"
+              icon="el-icon-delete"
+              @click="handleDelete(scope.row)"
+              v-hasPermi="['bs:technologyRouteChild:remove']"
+            >鍒犻櫎</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <el-empty v-else>
+        <span slot="description">鏆傛棤鏁版嵁</span>
+      </el-empty>
+    </el-card>
+
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 娣诲姞鎴栦慨鏀瑰伐鑹鸿矾绾垮瓙淇℃伅瀵硅瘽妗� -->
+    <el-dialog v-dialogpop-up :title="title" :visible.sync="open" width="500px" append-to-body>
+      <span slot="title">
+        <i class="el-icon-s-order"></i>
+        {{titleName}}
+      </span>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="娴佺▼缂栫爜">
+          <el-input v-model="queryRouteCode" :disabled="true" />
+        </el-form-item>
+<!--        <el-form-item label="宸ュ簭缂栫爜" prop="processesCode">-->
+<!--          <el-input v-model="form.processesCode" placeholder="璇疯緭鍏ュ伐搴忕紪鐮�" />-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="宸ュ簭鍚嶇О" prop="processesName">-->
+<!--          <el-input v-model="form.processesName" placeholder="璇疯緭鍏ュ伐搴忓悕绉�" />-->
+<!--        </el-form-item>-->
+        <el-form-item label="宸ュ簭鍚嶇О" prop="processesName">
+          <el-select style="width: 100%" v-model="form.processesCode" placeholder="璇烽�夋嫨">
+            <el-option
+              v-for="item in options"
+              :key="item.processesCode"
+              :label="item.processesName"
+              :value="item.processesCode">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="鍔犲伐椤哄簭" prop="stepNo">
+          <el-input v-model="form.stepNo" placeholder="璇疯緭鍏ュ姞宸ラ『搴�" />
+        </el-form-item>
+<!--        <el-form-item label="涓嬩竴閬撳伐搴�" prop="nextProcess">-->
+<!--          <el-input v-model="form.nextProcess" placeholder="璇疯緭鍏ヤ笅涓�閬撳伐搴�" />-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="涓嬩竴閬撳伐搴�" prop="nextProcess">-->
+<!--          <el-select style="width: 100%" v-model="form.processesCode" placeholder="璇烽�夋嫨">-->
+<!--            <el-option-->
+<!--              v-for="item in options"-->
+<!--              :key="item.processesCode"-->
+<!--              :label="item.processesName"-->
+<!--              :value="item.processesCode">-->
+<!--            </el-option>-->
+<!--          </el-select>-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="涓庝笅涓�閬撳伐搴忓叧绯�" prop="nextProcessBond">-->
+<!--          <el-input v-model="form.nextProcessBond" placeholder="璇疯緭鍏ヤ笌涓嬩竴閬撳伐搴忓叧绯�" />-->
+<!--        </el-form-item>-->
+
+        <el-form-item label="鏄惁鍏抽敭宸ュ簭" prop="keyProcessesFlag" label-width="180">
+          <el-radio-group v-model="form.keyProcessesFlag">
+            <el-radio
+              v-for="dict in dict.type.sys_yes_no"
+              :key="dict.value"
+              :label="dict.value"
+            >{{dict.label}}</el-radio>
+          </el-radio-group>
+        </el-form-item>
+<!--        <el-form-item label="鍑嗗鏃堕棿" prop="preparationTime">-->
+<!--          <el-input v-model="form.preparationTime" placeholder="璇疯緭鍏ュ噯澶囨椂闂�" />-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="绛夊緟鏃堕棿" prop="waitTime">-->
+<!--          <el-input v-model="form.waitTime" placeholder="璇疯緭鍏ョ瓑寰呮椂闂�" />-->
+<!--        </el-form-item>-->
+        <el-form-item label="澶囨敞" prop="remark">
+          <el-input v-model="form.remark" placeholder="璇疯緭鍏ュ娉�" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listProcesses} from "@/api/main/bs/processes/processes";
+import { listTechnologyRoute} from "@/api/main/bs/technologyRoute/technologyRoute";
+import { listTechnologyRouteChild, getTechnologyRouteChild, delTechnologyRouteChild, addTechnologyRouteChild, updateTechnologyRouteChild } from "@/api/main/bs/technologyRouteChild/technologyRouteChild";
+
+export default {
+  name: "TechnologyRouteChild",
+  dicts: ['sys_yes_no'],
+  data() {
+    return {
+      tableWidth: '100%', // 鍒濆瀹藉害璁剧疆涓�100%
+      options: [],
+      // 閬僵灞�
+      loading: true,
+      titleName: 'test',
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 宸ヨ壓璺嚎瀛愪俊鎭〃鏍兼暟鎹�
+      technologyRouteChildList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      queryRouteCode: "",
+      queryRouteId: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        processesCode: null,
+        processesName: null,
+        keyProcessesFlag: null,
+        routeCode: undefined,
+      },
+      headerInformationData:{
+        routeCode: "",
+        routeName: "",
+        productCode: "",
+        productName: ""
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        id: [
+          { required: true, message: "涓婚敭id涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        stepNo: [
+          { required: true, message: "鍔犲伐宸ュ簭涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+      }
+    };
+  },
+  created() {
+    let routeCode = this.$route.query.routeCode;
+    let routeId = this.$route.query.routeId;
+    this.queryParams.routeCode = routeCode
+    this.queryRouteCode = routeCode
+    this.queryRouteId = routeId
+    this.getList();
+    this.headerInformation();
+    this.getProcesses();
+  },
+  methods: {
+    getProcesses() {
+      listProcesses(null).then(response => {
+        this.options = response.rows;
+      });
+    },
+    /** 宸ヨ壓娴佺▼琛ㄥご淇℃伅 */
+    headerInformation() {
+      listTechnologyRoute(this.queryParams).then(response => {
+        this.headerInformationData = response.rows[0];
+      });
+    },
+    /** 杩斿洖鎸夐挳鎿嶄綔 */
+    handleClose() {
+      const obj = { path: "/main/pm/technologyRoute" };
+      this.$tab.closeOpenPage(obj);
+    },
+    /** 鏌ヨ宸ヨ壓璺嚎瀛愪俊鎭垪琛� */
+    getList() {
+      this.loading = true;
+      listTechnologyRouteChild(this.queryParams).then(response => {
+        this.technologyRouteChildList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        id: null,
+        processesCode: null,
+        processesName: null,
+        stepNo: null,
+        nextProcess: null,
+        nextProcessBond: null,
+        keyProcessesFlag: 'Y',
+        preparationTime: null,
+        waitTime: null,
+        createUser: null,
+        createTime: null,
+        updateUser: null,
+        updateTime: null,
+        remark: null,
+        routeId: null,
+        routeCode: null,
+        spareField1: null,
+        spareField2: null,
+        spareField3: null,
+        spareField4: null
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.titleName = "娣诲姞宸ヨ壓璺嚎瀛愪俊鎭�";
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getTechnologyRouteChild(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.titleName = "淇敼宸ヨ壓璺嚎瀛愪俊鎭�";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm() {
+      this.form.routeCode = this.queryRouteCode;
+      this.form.routeId =  this.queryRouteId;
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateTechnologyRouteChild(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addTechnologyRouteChild(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎宸ヨ壓璺嚎瀛愪俊鎭紪鍙蜂负"' + ids + '"鐨勬暟鎹」锛�').then(function() {
+        return delTechnologyRouteChild(ids);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('bs/technologyRouteChild/export', {
+        ...this.queryParams
+      }, `technologyRouteChild_${new Date().getTime()}.xlsx`)
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/main/bs/workshop/index.vue b/jcdm-ui/src/views/main/bs/workshop/index.vue
new file mode 100644
index 0000000..44c0311
--- /dev/null
+++ b/jcdm-ui/src/views/main/bs/workshop/index.vue
@@ -0,0 +1,335 @@
+<template>
+  <div class="app-container">
+    <el-card class="box-card">
+      <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+        <el-form-item label="杞﹂棿缂栫爜" prop="workshopCode">
+          <el-input
+            v-model="queryParams.workshopCode"
+            placeholder="璇疯緭鍏ヨ溅闂寸紪鐮�"
+            clearable
+            @keyup.enter.native="handleQuery"
+          />
+        </el-form-item>
+        <el-form-item label="杞﹂棿鍚嶇О" prop="workshopName">
+          <el-input
+            v-model="queryParams.workshopName"
+            placeholder="璇疯緭鍏ヨ溅闂村悕绉�"
+            clearable
+            @keyup.enter.native="handleQuery"
+          />
+        </el-form-item>
+        <el-form-item style="float: right">
+          <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+<!--          <el-button type="warning" icon="el-icon-copy-document" size="mini" @click="advancedQuery">楂樼骇鏌ヨ</el-button>-->
+          <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+        </el-form-item>
+      </el-form>
+      <el-form :model="queryParams" ref="queryParams" size="small" :inline="true" v-show="advancedShowSearch" label-width="68px">
+      </el-form>
+    </el-card>
+
+    <el-card style="margin-top: 10px" class="box-card">
+      <el-row :gutter="10" class="mb8">
+        <el-col :span="1.5">
+          <el-button
+            type="primary"
+            plain
+            icon="el-icon-plus"
+            size="mini"
+            @click="handleAdd"
+            v-hasPermi="['bs:workshop:add']"
+          >鏂板</el-button>
+        </el-col>
+        <el-col :span="1.5">
+          <el-button
+            type="success"
+            plain
+            icon="el-icon-edit"
+            size="mini"
+            :disabled="single"
+            @click="handleUpdate"
+            v-hasPermi="['bs:workshop:edit']"
+          >淇敼</el-button>
+        </el-col>
+        <el-col :span="1.5">
+          <el-button
+            type="danger"
+            plain
+            icon="el-icon-delete"
+            size="mini"
+            :disabled="multiple"
+            @click="handleDelete"
+            v-hasPermi="['bs:workshop:remove']"
+          >鍒犻櫎</el-button>
+        </el-col>
+        <el-col :span="1.5">
+          <el-button
+            type="warning"
+            plain
+            icon="el-icon-download"
+            size="mini"
+            @click="handleExport"
+            v-hasPermi="['bs:workshop:export']"
+          >瀵煎嚭</el-button>
+        </el-col>
+        <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+      </el-row>
+      <el-table v-loading="loading" border :data="workshopList" @selection-change="handleSelectionChange" v-if="workshopList.length > 0">
+        <el-table-column type="selection" width="55" align="center" />
+        <!--      <el-table-column label="id" align="center" prop="id" />-->
+        <el-table-column label="杞﹂棿缂栫爜" width="120" align="center" prop="workshopCode">
+        </el-table-column>
+        <el-table-column :show-overflow-tooltip='true' width="150" label="杞﹂棿鍚嶇О" align="center" prop="workshopName">
+        </el-table-column>
+        <el-table-column label="鐘舵��" align="center" prop="status" width="80">
+          <template slot-scope="scope">
+            <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
+          </template>
+        </el-table-column>
+        <el-table-column label="澶囨敞" width="150" align="center" prop="remarks">
+        </el-table-column>
+        <el-table-column label="鍒涘缓浜�" align="center" prop="createUser" width="150">
+        </el-table-column>
+        <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180">
+        </el-table-column>
+        <el-table-column label="鏇存柊浜�" align="center" prop="updateUser" width="150">
+        </el-table-column>
+        <el-table-column label="鏇存柊鏃堕棿" align="center" prop="updateTime" width="180">
+        </el-table-column>
+        <el-table-column fixed="right" label="鎿嶄綔" width="200" align="center" class-name="small-padding fixed-width">
+          <template slot-scope="scope">
+            <el-button
+              size="mini"
+              type="success"
+              plain
+              style="width: 72px"
+              icon="el-icon-edit"
+              @click="handleUpdate(scope.row)"
+              v-hasPermi="['bs:workshop:edit']"
+            >淇敼</el-button>
+            <el-button
+              size="mini"
+              plain
+              style="width: 72px"
+              type="danger"
+              icon="el-icon-delete"
+              @click="handleDelete(scope.row)"
+              v-hasPermi="['bs:workshop:remove']"
+            >鍒犻櫎</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <el-empty v-else>
+        <span slot="description">鏆傛棤鏁版嵁</span>
+      </el-empty>
+    </el-card>
+
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 娣诲姞鎴栦慨鏀硅溅闂翠俊鎭璇濇 -->
+    <el-dialog v-dialogpop-up :title="title" :visible.sync="open" width="500px" append-to-body>
+      <span slot="title">
+        <i class="el-icon-s-order"></i>
+        {{titleName}}
+      </span>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="杞﹂棿缂栫爜" prop="workshopCode">
+          <el-input v-model="form.workshopCode" placeholder="璇疯緭鍏ヨ溅闂寸紪鐮�" />
+        </el-form-item>
+        <el-form-item label="杞﹂棿鍚嶇О" prop="workshopName">
+          <el-input v-model="form.workshopName" placeholder="璇疯緭鍏ヨ溅闂村悕绉�" />
+        </el-form-item>
+        <el-form-item label="鐘舵��" prop="status">
+          <el-radio-group v-model="form.status">
+            <el-radio
+              v-for="dict in dict.type.sys_normal_disable"
+              :key="dict.value"
+              :label="dict.value"
+            >{{dict.label}}</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="澶囨敞" prop="remarks">
+          <el-input v-model="form.remarks" placeholder="璇疯緭鍏ュ娉�" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listWorkshop, getWorkshop, delWorkshop, addWorkshop, updateWorkshop } from "@/api/main/bs/workshop/workshop";
+
+export default {
+  name: "Workshop",
+  dicts: ['sys_normal_disable'],
+  data() {
+    return {
+      select: '',
+      // 閬僵灞�
+      loading: true,
+      titleName: 'test',
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      advancedShowSearch: false,
+
+      // 鎬绘潯鏁�
+      total: 0,
+      // 杞﹂棿淇℃伅琛ㄦ牸鏁版嵁
+      workshopList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        workshopCode: null,
+        workshopName: null,
+        remarks: null,
+        createUser: null
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        id: [
+          { required: true, message: "id涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        workshopCode: [
+          { required: true, message: "杞﹂棿缂栫爜涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        workshopName: [
+          { required: true, message: "杞﹂棿鍚嶇О涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    advancedQuery(){
+       this.advancedShowSearch = (this.advancedShowSearch) ? this.advancedShowSearch = false : this.advancedShowSearch = true;
+    },
+    /** 鏌ヨ杞﹂棿淇℃伅鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listWorkshop(this.queryParams).then(response => {
+        this.workshopList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        id: null,
+        workshopCode: null,
+        workshopName: null,
+        spareField1: null,
+        spareField2: null,
+        remarks: null,
+        createUser: null,
+        createTime: null,
+        updateUser: null,
+        status: "0",
+        updateTime: null
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.queryParams.remarks = null;
+      this.queryParams.createUser = null;
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.titleName = "娣诲姞杞﹂棿淇℃伅";
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getWorkshop(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.titleName = "淇敼杞﹂棿淇℃伅";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateWorkshop(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addWorkshop(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎杞﹂棿淇℃伅缂栧彿涓�"' + ids + '"鐨勬暟鎹」锛�').then(function() {
+        return delWorkshop(ids);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('bs/workshop/export', {
+        ...this.queryParams
+      }, `workshop_${new Date().getTime()}.xlsx`)
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/main/cfkb/Instructions/index.vue b/jcdm-ui/src/views/main/cfkb/Instructions/index.vue
new file mode 100644
index 0000000..2bf164b
--- /dev/null
+++ b/jcdm-ui/src/views/main/cfkb/Instructions/index.vue
@@ -0,0 +1,270 @@
+<template>
+  <div class="app-container">
+    <el-row :gutter="3">
+      <el-col :span="6">
+        <el-card shadow="always">
+          CFMOTO
+        </el-card>
+      </el-col>
+      <el-col :span="3">
+        <el-card shadow="always">
+          {{productCode}}
+        </el-card>
+      </el-col>
+      <el-col :span="15">
+        <el-card shadow="always">
+          瑁呭壇杞�,鎷ㄥ弶
+        </el-card>
+      </el-col>
+    </el-row>
+    <el-row :gutter="3" style="margin-top: 5px">
+      <el-col :span="6">
+        <div style="height: 600px;overflow: auto;">
+          <div  class="container" style="height: 50px;background-color: #00afff;margin-bottom: 10px">
+            <span class="centered">灞呬腑鏂囨湰</span>
+          </div>
+          <div v-for="(item,index) in tableData" :key="item.sort" class="outerDiv" :id="'outerDiv'+index">
+            <div class="innerDiv1">
+              <div class="innerDiv2">
+                <span class="content_left">{{ index+1 }}</span>
+              </div>
+              <div class="content_right">{{ item.address }}</div>
+            </div>
+          </div>
+        </div>
+      </el-col>
+      <el-col :span="18">
+        <el-col :span="20">
+          <el-card style="height: 600px" shadow="always">
+            <el-row style="height: 100px">
+              {{address}}
+            </el-row>
+            <el-row style="height: 400px">
+              <el-image style="height: 390px;width: 960px" :src="src"></el-image>
+<!--              {{src}}-->
+            </el-row>
+            <el-row style="height: 100px">
+              <el-button type="primary" @click="backClick()" style="float: left" icon="el-icon-arrow-left">涓婁竴姝�</el-button>
+              <el-button type="primary" @click="nextStep()" style="float: right">涓嬩竴姝�<i class="el-icon-arrow-right el-icon--right"></i></el-button>
+            </el-row>
+          </el-card>
+        </el-col>
+        <el-col :span="4">
+          <el-card style="height: 600px" shadow="always">
+            <el-row style="height: 100px;margin-top: 100px">
+              <el-button type="primary" @click="processDocuments()" style="float: left" icon="el-icon-folder-opened">宸ヨ壓鏂囦欢</el-button>
+            </el-row>
+            <el-row style="height: 50px;margin-top: 5px">
+              <el-button type="primary" @click="changeProducts('2V91')" style="width: 100px" icon="el-icon-s-unfold">2V91</el-button>
+            </el-row>
+            <el-row style="height: 50px;">
+              <el-button type="primary" @click="changeProducts('191')" style="width: 100px" icon="el-icon-s-unfold">191</el-button>
+            </el-row>
+            <el-row style="height: 50px;">
+              <el-button type="primary" @click="changeProducts('0JWF')" style="width: 100px" icon="el-icon-s-unfold">0JWF</el-button>
+            </el-row>
+          </el-card>
+        </el-col>
+
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import {listFormulaChild} from "@/api/main/bs/formulaChild/formulaChild";
+
+export default {
+  name: "Instructions",
+  data() {
+    return {
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        productCode: null,
+      },
+      productCode: '2V91',
+      tableData: [{
+        img: 'https://fuss10.elemecdn.com/e/5d/4a731a90594',
+        sort: '2',
+        address: '涓婃捣甯傛櫘闄�鍖洪噾娌欐睙璺� 1518 寮勪笂娴峰競鏅檧鍖洪噾娌欐睙璺� 1518 寮勪笂娴峰競鏅檧鍖洪噾娌欐睙璺� 1518 寮勪笂娴峰競鏅檧鍖洪噾娌欐睙璺� 1518 寮�'
+      }, {
+        img: 'https://fuss10.elemecdn.com/e/5d/4a731a90594',
+        sort: '2',
+        address: '涓婃捣甯傛櫘闄�鍖洪噾娌欐睙璺� 1518 寮勪笂娴峰競鏅檧鍖洪噾娌欐睙璺� 1518 寮勪笂娴峰競鏅檧鍖洪噾娌欐睙璺� 1518 寮勪笂娴峰競鏅檧鍖洪噾娌欐睙璺� 1518 寮�'
+      }, {
+        img: 'https://fuss10.elemecdn.com/e/5d/4a731a90594',
+        sort: '2',
+        address: '涓婃捣甯傛櫘闄�鍖洪噾娌欐睙璺� 1519 寮�'
+      }, {
+        img: 'htts://fuss10.elemecdn.com/e/5d/4a731a90594',
+        sort: '2',
+        address: '涓婃捣甯傛櫘闄�鍖洪噾娌欐睙璺� 1516 寮�'
+      }, {
+        img: 'https://fuss10.elemecdn.com/e/5d/4a731a90594',
+        sort: '2',
+        address: '涓婃捣甯傛櫘闄�鍖洪噾娌欐睙璺� 1516 寮�'
+      }, {
+        img: 'https://fuss10.elemecdn.com/e/5d/4a731a90594',
+        sort: '2',
+        address: '涓婃捣甯傛櫘闄�鍖洪噾娌欐睙璺� 1516 寮�'
+      }, {
+        img: 'https://fuss10.elemecdn.com/e/5d/4a731a90594',
+        sort: '2',
+        address: '涓婃捣甯傛櫘闄�鍖洪噾娌欐睙璺� 1516 寮�'
+      }, {
+        img: '222222222222',
+        sort: '2',
+        address: '涓婃捣甯傛櫘闄�鍖洪噾娌欐睙璺� 1516 寮�'
+      }, {
+        img: 'https://fuss10.elemecdn.com/e/5d/4a731a90594',
+        sort: '2',
+        address: '涓婃捣甯傛櫘闄�鍖洪噾娌欐睙璺� 1516 寮�'
+      }, {
+        img: 'https://fuss10.elemecdn.com/e/5d/4a731a90594',
+        sort: '2',
+        address: '涓婃捣甯傛櫘闄�鍖洪噾娌欐睙璺� 1516 寮�'
+      }, {
+        img: 'https://fuss10.elemecdn.com/e/5d/4a731a90594',
+        sort: '2',
+        address: '涓婃捣甯傛櫘闄�鍖洪噾娌欐睙璺� 1516 寮�'
+      }],
+      address: '',
+      src: 'https://cube.elemecdn.com/6/94/4d3ea53c084bad6931a56d5158a48jpeg.jpeg',
+      // src: 'file:///D:/img/qt.jpg'
+
+      intervalId: null,
+
+    };
+  },
+  created() {
+    this.tableData = []
+  },
+  mounted() {
+    this.changeProducts(this.productCode)
+    // this.autoShow()
+  },
+  beforeDestroy() {
+    clearInterval(this.intervalId)
+    this.intervalId = null
+  },
+  methods: {
+    // 瀹氭椂瑙﹀彂
+    autoShow() {
+      const _this = this
+      this.intervalId = setInterval(() => {
+        _this.setBg()
+      }, 2000)
+    },
+    setImg(index) {
+      this.address = this.tableData[index].address
+      this.src = this.tableData[index].img
+    },
+    setBg() {
+      if (document.getElementById('outerDiv' + (this.tableData.length - 1)).style.background === 'yellow') {
+        this.setImg(0)
+        document.getElementById('outerDiv0').style.background = 'yellow'
+        for (let j = 1; j < this.tableData.length; j++) {
+          document.getElementById('outerDiv' + j).style.background = 'white'
+        }
+        return;
+      }
+      for (let i = 0; i < this.tableData.length - 1; i++) {
+        if (document.getElementById('outerDiv' + i).style.background === 'yellow') {
+          this.setImg(i+1)
+          document.getElementById('outerDiv' + i).style.background = 'green'
+          document.getElementById('outerDiv' + (i+1)).style.background = 'yellow'
+          return;
+        }
+      }
+    },
+    getUpOrDown(index) {
+      for (let i = 0; i < this.tableData.length; i++) {
+        if (document.getElementById('outerDiv' + i).style.background === 'yellow') {
+          this.setImg(i + index)
+          document.getElementById('outerDiv' + i).style.background = index < 0 ? 'white' : 'green'
+          document.getElementById('outerDiv' + (i + index)).style.background = 'yellow'
+          return;
+        }
+      }
+    },
+    backClick(){
+      this.getUpOrDown(-1)
+    },
+    nextStep(){
+      this.getUpOrDown(1)
+    },
+    processDocuments(){
+
+    },
+    changeProducts(val){
+
+      this.productCode = val
+      const _this = this
+
+      /** 鏌ヨ閰嶆柟閰嶇疆瀛愪俊鎭垪琛� */
+      this.queryParams.productCode = val;
+      listFormulaChild(this.queryParams).then(response => {
+        // this.tableData = [];
+        this.tableData = response.rows;
+        this.$nextTick(() => {
+          clearInterval(this.intervalId);
+          document.getElementById('outerDiv0').style.background = 'yellow'
+          this.setImg(0)
+          this.autoShow()
+        })
+
+
+      });
+    },
+  },
+}
+</script>
+
+<style scoped>
+.outerDiv {
+  width: fit-content;
+  min-width: 100%;
+  /*width: 300px;*/
+  height: 50px;
+  margin-bottom: 10px;
+}
+
+.innerDiv1 {
+  /*width: 79%;*/
+  height: 100%;
+  display: flex;
+  align-items: center;
+  border: 1px solid black;
+}
+
+.innerDiv2 {
+  /*width: 20%;*/
+  width: 50px;
+  height: 100%;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  border: 1px solid black;
+}
+
+.content_left {
+  font-weight: bold;
+}
+.content_right {
+  white-space: nowrap;
+  padding-left: 5px;
+  padding-right: 5px;
+}
+.container {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  height: 100px; /* 璁剧疆div鐨勯珮搴︼紝鍙牴鎹疄闄呮儏鍐佃皟鏁� */
+}
+
+.centered {
+  text-align: center;
+}
+
+</style>
diff --git a/jcdm-ui/src/views/main/da/collectionParamConf/index.vue b/jcdm-ui/src/views/main/da/collectionParamConf/index.vue
new file mode 100644
index 0000000..79e1b0e
--- /dev/null
+++ b/jcdm-ui/src/views/main/da/collectionParamConf/index.vue
@@ -0,0 +1,443 @@
+<template>
+  <div class="app-container">
+    <el-card class="box-card">
+        <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+          <el-form-item label="宸ュ簭缂栧彿" prop="processesCode">
+            <el-input
+              v-model="queryParams.processesCode"
+              placeholder="璇疯緭鍏ュ伐搴忕紪鍙�"
+              clearable
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+<!--          <el-form-item label="鍙傛暟闆嗙紪鐮�" prop="parameterSetCode">-->
+<!--            <el-input-->
+<!--              v-model="queryParams.parameterSetCode"-->
+<!--              placeholder="璇疯緭鍏ュ弬鏁伴泦缂栫爜"-->
+<!--              clearable-->
+<!--              @keyup.enter.native="handleQuery"-->
+<!--            />-->
+<!--          </el-form-item>-->
+<!--          <el-form-item label="鍙傛暟闆嗗悕绉�" prop="parameterSetName">-->
+<!--            <el-input-->
+<!--              v-model="queryParams.parameterSetName"-->
+<!--              placeholder="璇疯緭鍏ュ弬鏁伴泦鍚嶇О"-->
+<!--              clearable-->
+<!--              @keyup.enter.native="handleQuery"-->
+<!--            />-->
+<!--          </el-form-item>-->
+<!--          <el-form-item label="閲囬泦鍙傛暟ID" prop="collectParameterId">-->
+<!--            <el-input-->
+<!--              v-model="queryParams.collectParameterId"-->
+<!--              placeholder="璇疯緭鍏ラ噰闆嗗弬鏁癐D"-->
+<!--              clearable-->
+<!--              @keyup.enter.native="handleQuery"-->
+<!--            />-->
+<!--          </el-form-item>-->
+<!--          <el-form-item label="閲囬泦鍙傛暟鍚嶇О" prop="collectParameterName">-->
+<!--            <el-input-->
+<!--              v-model="queryParams.collectParameterName"-->
+<!--              placeholder="璇疯緭鍏ラ噰闆嗗弬鏁板悕绉�"-->
+<!--              clearable-->
+<!--              @keyup.enter.native="handleQuery"-->
+<!--            />-->
+<!--          </el-form-item>-->
+<!--          <el-form-item label="鏄惁浣滀负瀵规瘮鍙傛暟" prop="contrastParameterFlag">-->
+<!--            <el-input-->
+<!--              v-model="queryParams.contrastParameterFlag"-->
+<!--              placeholder="璇疯緭鍏ユ槸鍚︿綔涓哄姣斿弬鏁�"-->
+<!--              clearable-->
+<!--              @keyup.enter.native="handleQuery"-->
+<!--            />-->
+<!--          </el-form-item>-->
+<!--          <el-form-item label="閲囬泦鍙傛暟绫诲瀷" prop="collectParameterType">-->
+<!--            <el-select v-model="queryParams.collectParameterType" placeholder="璇烽�夋嫨閲囬泦鍙傛暟绫诲瀷" clearable>-->
+<!--              <el-option-->
+<!--                v-for="dict in dict.type.${dictType}"-->
+<!--                :key="dict.value"-->
+<!--                :label="dict.label"-->
+<!--                :value="dict.value"-->
+<!--              />-->
+<!--            </el-select>-->
+<!--          </el-form-item>-->
+          <el-form-item label="浜у搧缂栫爜" prop="productCode">
+            <el-input
+              v-model="queryParams.productCode"
+              placeholder="璇疯緭鍏ヤ骇鍝佺紪鐮�"
+              clearable
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item style="float: right">
+            <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+            <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+          </el-form-item>
+        </el-form>
+    </el-card>
+
+    <el-card style="margin-top: 10px" class="box-card">
+        <el-row :gutter="10" class="mb8">
+          <el-col :span="1.5">
+            <el-button
+              type="primary"
+              plain
+              icon="el-icon-plus"
+              size="mini"
+              @click="handleAdd"
+              v-hasPermi="['da:collectionParamConf:add']"
+            >鏂板</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="success"
+              plain
+              icon="el-icon-edit"
+              size="mini"
+              :disabled="single"
+              @click="handleUpdate"
+              v-hasPermi="['da:collectionParamConf:edit']"
+            >淇敼</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="danger"
+              plain
+              icon="el-icon-delete"
+              size="mini"
+              :disabled="multiple"
+              @click="handleDelete"
+              v-hasPermi="['da:collectionParamConf:remove']"
+            >鍒犻櫎</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="warning"
+              plain
+              icon="el-icon-download"
+              size="mini"
+              @click="handleExport"
+              v-hasPermi="['da:collectionParamConf:export']"
+            >瀵煎嚭</el-button>
+          </el-col>
+          <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+        </el-row>
+
+        <el-table border v-loading="loading" :data="collectionParamConfList" @selection-change="handleSelectionChange">
+          <el-table-column type="selection" width="55" align="center" />
+<!--          <el-table-column label="涓婚敭id" align="center" prop="id" />-->
+          <el-table-column label="浜у搧缂栫爜" align="center" width="150" prop="productCode">
+          </el-table-column>
+          <el-table-column label="宸ュ簭缂栧彿" align="center" width="80" prop="processesCode">
+          </el-table-column>
+          <el-table-column label="鍙傛暟闆嗙紪鐮�" align="center" width="130" prop="parameterSetCode">
+          </el-table-column>
+          <el-table-column label="鍙傛暟闆嗗悕绉�" align="center" width="160" prop="parameterSetName">
+          </el-table-column>
+          <el-table-column label="鍙傛暟缂栫爜" align="center" width="130" prop="collectParameterId">
+          </el-table-column>
+          <el-table-column label="鍙傛暟鍚嶇О" align="center" width="160" prop="collectParameterName">
+          </el-table-column>
+<!--          <el-table-column label="鏄惁浣滀负瀵规瘮鍙傛暟" align="center" prop="contrastParameterFlag">-->
+<!--          </el-table-column>-->
+
+          <el-table-column label="閲囬泦鍦板潃" align="center" width="180" prop="gatherAddress">
+          </el-table-column>
+          <el-table-column label="閲囬泦椤哄簭" align="center" width="80" prop="gatherSequence">
+          </el-table-column>
+
+          <el-table-column label="鍙傛暟绫诲瀷" align="center" width="130" prop="collectParameterType">
+          </el-table-column>
+          <el-table-column label="鍗曚綅" align="center" width="80" prop="collectParameterUnit">
+          </el-table-column>
+<!--          <el-table-column label="鏁版嵁鎻忚堪" align="center" width="160" prop="Descriptives">
+          </el-table-column>-->
+          <el-table-column label="涓婇檺鍊�" align="center" prop="paramUpper">
+          </el-table-column>
+          <el-table-column label="涓嬮檺鍊�" align="center" prop="paramLower">
+          </el-table-column>
+          <el-table-column label="涓績鍊�" align="center" prop="paramCentral">
+          </el-table-column>
+
+          <el-table-column label="澶囨敞" align="center" width="160" prop="remarks">
+          </el-table-column>
+          <el-table-column label="鍒涘缓鐢ㄦ埛" align="center" prop="createUser">
+          </el-table-column>
+          <el-table-column label="鍒涘缓鏃堕棿" align="center" width="160" prop="createTime">
+          </el-table-column>
+          <el-table-column label="鏇存敼鐢ㄦ埛" align="center" prop="updateUser">
+          </el-table-column>
+          <el-table-column label="鏇存敼鏃堕棿" align="center" width="160" prop="updateTime">
+          </el-table-column>
+          <el-table-column fixed="right" width="200" label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+            <template slot-scope="scope">
+              <el-button
+                size="mini"
+                type="success"
+                plain
+                style="width: 72px"
+                icon="el-icon-edit"
+                @click="handleUpdate(scope.row)"
+                v-hasPermi="['da:collectionParamConf:edit']"
+              >淇敼</el-button>
+              <el-button
+                size="mini"
+                type="danger"
+                plain
+                style="width: 72px"
+                icon="el-icon-delete"
+                @click="handleDelete(scope.row)"
+                v-hasPermi="['da:collectionParamConf:remove']"
+              >鍒犻櫎</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+    </el-card>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 娣诲姞鎴栦慨鏀归噰闆嗗弬鏁伴厤缃璇濇 -->
+    <el-dialog v-dialogpop-up :title="title" :visible.sync="open" width="700px" append-to-body>
+      <span slot="title">
+        <i class="el-icon-s-order"></i>
+        {{titleName}}
+      </span>
+      <el-form ref="form" inline :model="form" :rules="rules" label-width="120px">
+        <el-form-item label="宸ュ簭缂栧彿" prop="processesCode">
+          <el-input v-model="form.processesCode" placeholder="璇疯緭鍏ュ伐搴忕紪鍙�" />
+        </el-form-item>
+        <el-form-item label="鍙傛暟闆嗙紪鐮�" prop="parameterSetCode">
+          <el-input v-model="form.parameterSetCode" placeholder="璇疯緭鍏ュ弬鏁伴泦缂栫爜" />
+        </el-form-item>
+        <el-form-item label="鍙傛暟闆嗗悕绉�" prop="parameterSetName">
+          <el-input v-model="form.parameterSetName" placeholder="璇疯緭鍏ュ弬鏁伴泦鍚嶇О" />
+        </el-form-item>
+        <el-form-item label="閲囬泦鍙傛暟ID" prop="collectParameterId">
+          <el-input v-model="form.collectParameterId" placeholder="璇疯緭鍏ラ噰闆嗗弬鏁癐D" />
+        </el-form-item>
+        <el-form-item label="閲囬泦鍙傛暟鍚嶇О" prop="collectParameterName">
+          <el-input v-model="form.collectParameterName" placeholder="璇疯緭鍏ラ噰闆嗗弬鏁板悕绉�" />
+        </el-form-item>
+        <el-form-item label="鏄惁浣滀负瀵规瘮鍙傛暟" prop="contrastParameterFlag">
+          <el-input v-model="form.contrastParameterFlag" placeholder="璇疯緭鍏ユ槸鍚︿綔涓哄姣斿弬鏁�" />
+        </el-form-item>
+<!--        <el-form-item label="閲囬泦鍙傛暟绫诲瀷" prop="collectParameterType">-->
+<!--          <el-select v-model="form.collectParameterType" placeholder="璇烽�夋嫨閲囬泦鍙傛暟绫诲瀷">-->
+<!--            <el-option-->
+<!--              v-for="dict in dict.type.${dictType}"-->
+<!--              :key="dict.value"-->
+<!--              :label="dict.label"-->
+<!--              :value="dict.value"-->
+<!--            ></el-option>-->
+<!--          </el-select>-->
+<!--        </el-form-item>-->
+        <el-form-item label="閲囬泦鍙傛暟鍗曚綅" prop="collectParameterUnit">
+          <el-input v-model="form.collectParameterUnit" placeholder="璇疯緭鍏ラ噰闆嗗弬鏁板崟浣�" />
+        </el-form-item>
+        <el-form-item label="鏁版嵁鎻忚堪" prop="Descriptives">
+          <el-input v-model="form.Descriptives" placeholder="璇疯緭鍏ユ暟鎹弿杩�" />
+        </el-form-item>
+        <el-form-item label="涓婇檺鍊�" prop="paramUpper">
+          <el-input v-model="form.paramUpper" placeholder="璇疯緭鍏ヤ笂闄愬��" />
+        </el-form-item>
+        <el-form-item label="涓嬮檺鍊�" prop="paramLower">
+          <el-input v-model="form.paramLower" placeholder="璇疯緭鍏ヤ笅闄愬��" />
+        </el-form-item>
+        <el-form-item label="涓績鍊�" prop="paramCentral">
+          <el-input v-model="form.paramCentral" placeholder="璇疯緭鍏ヤ腑蹇冨��" />
+        </el-form-item>
+        <el-form-item label="浜у搧缂栫爜" prop="productCode">
+          <el-input v-model="form.productCode" placeholder="璇疯緭鍏ヤ骇鍝佺紪鐮�" />
+        </el-form-item>
+        <el-form-item label="閲囬泦鍦板潃" prop="gatherAddress">
+          <el-input v-model="form.gatherAddress" placeholder="璇疯緭鍏ラ噰闆嗗湴鍧�" />
+        </el-form-item>
+        <el-form-item label="閲囬泦椤哄簭" prop="gatherSequence">
+          <el-input v-model="form.gatherSequence" placeholder="璇疯緭鍏ラ噰闆嗛『搴�" />
+        </el-form-item>
+        <el-form-item label="澶囨敞" prop="remarks">
+          <el-input v-model="form.remarks" placeholder="璇疯緭鍏ュ娉�" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listCollectionParamConf, getCollectionParamConf, delCollectionParamConf, addCollectionParamConf, updateCollectionParamConf } from "@/api/main/da/collectionParamConf/collectionParamConf";
+
+export default {
+  name: "CollectionParamConf",
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      titleName: "",
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 閲囬泦鍙傛暟閰嶇疆琛ㄦ牸鏁版嵁
+      collectionParamConfList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        processesCode: null,
+        parameterSetCode: null,
+        parameterSetName: null,
+        collectParameterId: null,
+        collectParameterName: null,
+        contrastParameterFlag: null,
+        collectParameterType: null,
+        productCode: null,
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        id: [
+          { required: true, message: "涓婚敭id涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 鏌ヨ閲囬泦鍙傛暟閰嶇疆鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listCollectionParamConf(this.queryParams).then(response => {
+        this.collectionParamConfList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        id: null,
+        processesCode: null,
+        parameterSetCode: null,
+        parameterSetName: null,
+        collectParameterId: null,
+        collectParameterName: null,
+        contrastParameterFlag: null,
+        collectParameterType: null,
+        collectParameterUnit: null,
+        Descriptives: null,
+        paramUpper: null,
+        paramLower: null,
+        paramCentral: null,
+        productCode: null,
+        gatherAddress: null,
+        gatherSequence: null,
+        remarks: null,
+        createUser: null,
+        createTime: null,
+        updateUser: null,
+        updateTime: null,
+        spareField1: null,
+        spareField2: null,
+        spareField3: null,
+        spareField4: null
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.titleName = "娣诲姞閲囬泦鍙傛暟閰嶇疆";
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getCollectionParamConf(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.titleName = "淇敼閲囬泦鍙傛暟閰嶇疆";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateCollectionParamConf(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addCollectionParamConf(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎閲囬泦鍙傛暟閰嶇疆缂栧彿涓�"' + ids + '"鐨勬暟鎹」锛�').then(function() {
+        return delCollectionParamConf(ids);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('da/collectionParamConf/export', {
+        ...this.queryParams
+      }, `collectionParamConf_${new Date().getTime()}.xlsx`)
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/main/da/opcuaconfig/index.vue b/jcdm-ui/src/views/main/da/opcuaconfig/index.vue
new file mode 100644
index 0000000..17215a4
--- /dev/null
+++ b/jcdm-ui/src/views/main/da/opcuaconfig/index.vue
@@ -0,0 +1,426 @@
+<template>
+  <div class="app-container">
+    <el-card class="box-card">
+        <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+          <el-form-item label="鑺傜偣" prop="node">
+            <el-input
+              v-model="queryParams.node"
+              placeholder="璇疯緭鍏ヨ妭鐐�"
+              clearable
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item label="璁㈤槄绫诲瀷" prop="rFunction">
+            <el-select v-model="queryParams.rFunction" placeholder="璇烽�夋嫨璁㈤槄绫诲瀷" clearable>
+              <el-option
+                v-for="dict in dict.type.subscription_type"
+                :key="dict.value"
+                :label="dict.label"
+                :value="dict.value"
+              />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="宸ュ簭缂栫爜" prop="process">
+            <el-input
+              v-model="queryParams.process"
+              placeholder="璇疯緭鍏ュ伐搴忕紪鐮�"
+              clearable
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item label="鐘舵��" prop="state">
+            <el-select v-model="queryParams.state" placeholder="璇烽�夋嫨鐘舵��" clearable>
+              <el-option
+                v-for="dict in dict.type.sys_normal_disable"
+                :key="dict.value"
+                :label="dict.label"
+                :value="dict.value"
+              />
+            </el-select>
+          </el-form-item>
+          <el-form-item style="float: right">
+            <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+            <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+          </el-form-item>
+        </el-form>
+    </el-card>
+
+    <el-card style="margin-top: 10px" class="box-card">
+        <el-row :gutter="10" class="mb8">
+          <el-col :span="1.5">
+            <el-button
+              type="primary"
+              plain
+              icon="el-icon-plus"
+              size="mini"
+              @click="handleAdd"
+              v-hasPermi="['da:opcuaconfig:add']"
+            >鏂板</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="success"
+              plain
+              icon="el-icon-edit"
+              size="mini"
+              :disabled="single"
+              @click="handleUpdate"
+              v-hasPermi="['da:opcuaconfig:edit']"
+            >淇敼</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="danger"
+              plain
+              icon="el-icon-delete"
+              size="mini"
+              :disabled="multiple"
+              @click="handleDelete"
+              v-hasPermi="['da:opcuaconfig:remove']"
+            >鍒犻櫎</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="warning"
+              plain
+              icon="el-icon-download"
+              size="mini"
+              @click="handleExport"
+              v-hasPermi="['main:opcuaconfig:export']"
+            >瀵煎嚭</el-button>
+          </el-col>
+          <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+        </el-row>
+
+        <el-table border v-loading="loading" :data="opcuaconfigList" @selection-change="handleSelectionChange">
+          <el-table-column type="selection" width="55" align="center" />
+<!--          <el-table-column label="ID" align="center" prop="id" />-->
+          <el-table-column label="宸ュ簭鍚嶇О" align="center" prop="processName">
+            <!--            <template slot-scope="scope">-->
+            <!--              <dict-tag :options="dict.type.${column.dictType}" :value="scope.row.processName"/>-->
+            <!--            </template>-->
+          </el-table-column>
+          <el-table-column label="宸ュ簭缂栫爜" align="center" prop="process">
+            <!--            <template slot-scope="scope">-->
+            <!--              <dict-tag :options="dict.type.${column.dictType}" :value="scope.row.process"/>-->
+            <!--            </template>-->
+          </el-table-column>
+          <el-table-column label="浜や簰鑺傜偣" align="center" prop="node">
+<!--            <template slot-scope="scope">-->
+<!--              <dict-tag :options="dict.type.${column.dictType}" :value="scope.row.node"/>-->
+<!--            </template>-->
+          </el-table-column>
+          <el-table-column label="鏁版嵁绫诲瀷" align="center" prop="sysTypes">
+            <template slot-scope="scope">
+              <dict-tag :options="dict.type.data_type" :value="scope.row.sysTypes"/>
+            </template>
+          </el-table-column>
+          <el-table-column label="鏄惁璁㈤槄" align="center" prop="subscribe">
+            <template slot-scope="scope">
+              <dict-tag :options="dict.type.sys_yes_no" :value="scope.row.subscribe"/>
+            </template>
+          </el-table-column>
+          <el-table-column label="璁㈤槄绫诲瀷" align="center" prop="rFunction">
+            <template slot-scope="scope">
+              <dict-tag :options="dict.type.subscription_type" :value="scope.row.rFunction"/>
+            </template>
+          </el-table-column>
+          <el-table-column label="鐘舵��" align="center" prop="state">
+            <template slot-scope="scope">
+              <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.state"/>
+            </template>
+          </el-table-column>
+          <el-table-column label="澶囨敞" align="center" prop="remarks">
+            <!--            <template slot-scope="scope">-->
+            <!--              <dict-tag :options="dict.type.${column.dictType}" :value="scope.row.remarks"/>-->
+            <!--            </template>-->
+          </el-table-column>
+          <el-table-column fixed="right" width="200" label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+            <template slot-scope="scope">
+              <el-button
+                size="mini"
+                type="success"
+                plain
+                style="width: 72px"
+                icon="el-icon-edit"
+                @click="handleUpdate(scope.row)"
+                v-hasPermi="['main:opcuaconfig:edit']"
+              >淇敼</el-button>
+              <el-button
+                size="mini"
+                type="danger"
+                plain
+                style="width: 72px"
+                icon="el-icon-delete"
+                @click="handleDelete(scope.row)"
+                v-hasPermi="['main:opcuaconfig:remove']"
+              >鍒犻櫎</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+    </el-card>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 娣诲姞鎴栦慨鏀逛氦浜掍俊鍙烽厤缃璇濇 -->
+    <el-dialog v-dialogpop-up :title="title" :visible.sync="open" width="500px" append-to-body>
+      <span slot="title">
+        <i class="el-icon-s-order"></i>
+        {{titleName}}
+      </span>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="浜や簰鑺傜偣" prop="node">
+          <el-input v-model="form.node" placeholder="璇疯緭鍏ヨ妭鐐�" />
+        </el-form-item>
+        <el-form-item label="鏁版嵁绫诲瀷" prop="sysTypes">
+          <el-select v-model="form.sysTypes" placeholder="璇烽�夋嫨鏁版嵁绫诲瀷">
+            <el-option
+              v-for="dict in dict.type.data_type"
+              :key="dict.value"
+              :label="dict.label"
+              :value="dict.value"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="鏄惁璁㈤槄" prop="subscribe">
+          <el-select v-model="form.subscribe" placeholder="璇烽�夋嫨鏄惁璁㈤槄">
+            <el-option
+              v-for="dict in dict.type.sys_yes_no"
+              :key="dict.value"
+              :label="dict.label"
+              :value="dict.value"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="璁㈤槄绫诲瀷" prop="rFunction">
+          <el-select v-model="form.rFunction" placeholder="璇烽�夋嫨璁㈤槄绫诲瀷">
+            <el-option
+              v-for="dict in dict.type.subscription_type"
+              :key="dict.value"
+              :label="dict.label"
+              :value="dict.value"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+<!--        <el-form-item label="宸ュ簭鍚嶇О" prop="processName">-->
+<!--          <el-input v-model="form.processName" placeholder="璇疯緭鍏ュ伐搴忓悕绉�" />-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="宸ュ簭缂栫爜" prop="process">-->
+<!--          <el-input v-model="form.process" placeholder="璇疯緭鍏ュ伐搴忕紪鐮�" />-->
+<!--        </el-form-item>-->
+        <el-form-item label="宸ュ簭缂栫爜" prop="process">
+          <el-select style="width: 100%" @change="handleSelectChange(form.process)" v-model="form.process" placeholder="璇烽�夋嫨">
+            <el-option
+              v-for="item in options"
+              :key="item.processesCode"
+              :label="item.processesCode"
+              :value="item.processesCode">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="宸ュ簭鍚嶇О" prop="processName">
+          <el-input disabled v-model="form.processName" placeholder="璇疯緭鍏ュ伐搴忓悕绉�" />
+        </el-form-item>
+        <el-form-item label="鐘舵��" prop="state">
+          <el-select v-model="form.state" placeholder="璇烽�夋嫨鐘舵��">
+            <el-option
+              v-for="dict in dict.type.sys_normal_disable"
+              :key="dict.value"
+              :label="dict.label"
+              :value="parseInt(dict.value)"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="澶囨敞" prop="remarks">
+          <el-input v-model="form.remarks" placeholder="璇疯緭鍏ュ娉�" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listOpcuaconfig, getOpcuaconfig, delOpcuaconfig, addOpcuaconfig, updateOpcuaconfig } from "@/api/main/da/opcuaconfig/opcuaconfig";
+import {listProcesses} from "@/api/main/bs/processes/processes";
+
+export default {
+  name: "Opcuaconfig",
+  dicts: ['subscription_type', 'sys_yes_no', 'data_type','sys_normal_disable'],
+  data() {
+    return {
+      options: [],
+      // 閬僵灞�
+      loading: true,
+      titleName: "",
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 浜や簰淇″彿閰嶇疆琛ㄦ牸鏁版嵁
+      opcuaconfigList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        node: null,
+        rFunction: null,
+        process: null,
+        state: null
+      },
+      ProcessesqueryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        process: null,
+        processName: null,
+        keyProcessesFlag: null,
+        routeCode: undefined,
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        id: [
+          { required: true, message: "ID涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+      }
+    };
+  },
+  created() {
+    this.getList();
+    this.getProcessesList();
+
+  },
+  methods: {
+    /** 鏌ヨ宸ュ簭淇℃伅鍒楄〃 */
+    getProcessesList() {
+      this.loading = true;
+      listProcesses(this.queryParams).then(response => {
+        this.options = response.rows;
+      });
+    },
+    handleSelectChange(selectedOption) {
+      this.ProcessesqueryParams.process = selectedOption;
+      listProcesses(this.ProcessesqueryParams).then(response => {
+        this.form.processName = response.rows[0].processesName;
+      });
+    },
+    /** 鏌ヨ浜や簰淇″彿閰嶇疆鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listOpcuaconfig(this.queryParams).then(response => {
+        this.opcuaconfigList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        id: null,
+        node: null,
+        sysTypes: null,
+        subscribe: null,
+        rFunction: null,
+        remarks: null,
+        processName: null,
+        process: null,
+        state: null
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.titleName = "娣诲姞浜や簰淇″彿閰嶇疆";
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getOpcuaconfig(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.titleName = "淇敼浜や簰淇″彿閰嶇疆";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateOpcuaconfig(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addOpcuaconfig(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎浜や簰淇″彿閰嶇疆缂栧彿涓�"' + ids + '"鐨勬暟鎹」锛�').then(function() {
+        return delOpcuaconfig(ids);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('da/opcuaconfig/export', {
+        ...this.queryParams
+      }, `opcuaconfig_${new Date().getTime()}.xlsx`)
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/main/da/paramCollection/index.vue b/jcdm-ui/src/views/main/da/paramCollection/index.vue
new file mode 100644
index 0000000..c4cded5
--- /dev/null
+++ b/jcdm-ui/src/views/main/da/paramCollection/index.vue
@@ -0,0 +1,374 @@
+<template>
+  <div class="app-container">
+    <el-card class="box-card">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="浜у搧缂栫爜" prop="productCode">
+        <el-input
+          v-model="queryParams.productCode"
+          placeholder="璇疯緭鍏ヤ骇鍝佺紪鐮�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="浜у搧鍚嶇О" prop="productName">
+        <el-input
+          v-model="queryParams.productName"
+          placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item style="float: right">
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+    </el-card>
+    <el-card style="margin-top: 10px" class="box-card">
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['main:paramCollection:add']"
+        >鏂板</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['main:paramCollection:edit']"
+        >淇敼</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['main:paramCollection:remove']"
+        >鍒犻櫎</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['main:paramCollection:export']"
+        >瀵煎嚭</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" border :data="paramCollectionList" @selection-change="handleSelectionChange" v-if="paramCollectionList.length > 0">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="宸ュ崟缂栧彿" align="center" prop="workOrderNo"></el-table-column>
+      <el-table-column label="鎬绘垚搴忓垪鍙�" align="center" width="140" prop="sfcCode" ></el-table-column>
+      <el-table-column label="浜у搧缂栧彿" align="center" prop="productCode"></el-table-column>
+      <el-table-column label="浜х嚎缂栧彿" align="center" prop="productionLine"></el-table-column>
+      <el-table-column label="宸ヤ綅缂栧彿" align="center" prop="locationCode"></el-table-column>
+      <el-table-column label="璁惧缂栧彿" align="center" prop="equipmentNo"></el-table-column>
+      <el-table-column label="鍙傛暟缂栫爜" align="center" prop="paramCode"></el-table-column>
+      <el-table-column label="鍙傛暟鍊�" align="center" prop="paramValue"></el-table-column>
+      <el-table-column label="鍙傛暟涓婇檺" align="center" prop="paramUpper"></el-table-column>
+      <el-table-column label="鍙傛暟涓嬮檺" align="center" prop="paramLower"></el-table-column>
+      <el-table-column label="閲囬泦鏃堕棿" align="center" prop="collectionTime" width="160">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.collectionTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="鐘舵��" align="center" prop="state"></el-table-column>
+      <el-table-column label="鍙傛暟鍚嶇О" align="center" prop="paramName" width="150" ></el-table-column>
+      <el-table-column label="鍗曚綅" align="center" prop="unit"></el-table-column>
+      <el-table-column label="绫诲瀷" align="center" prop="type"></el-table-column>
+      <el-table-column fixed="right" width="200" label="鎿嶄綔" align="center" class-name="small-padding fixed-width" >
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="success"
+            plain
+            style="width: 72px"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['main:paramCollection:edit']"
+          >淇敼</el-button>
+          <el-button
+            size="mini"
+            type="danger"
+            plain
+            style="width: 72px"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['main:paramCollection:remove']"
+          >鍒犻櫎</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+      <el-empty v-else>
+        <span slot="description">鏆傛棤鏁版嵁</span>
+      </el-empty>
+    </el-card>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 娣诲姞鎴栦慨鏀硅澶囦骇鍝佽繃绋嬪弬鏁伴噰闆嗗璇濇 -->
+    <el-dialog v-dialogpop-up :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="宸ュ崟缂栧彿" prop="workOrderNo">
+          <el-input v-model="form.workOrderNo" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
+        </el-form-item>
+        <el-form-item label="鎬绘垚搴忓垪鍙�" prop="sfcCode">
+          <el-input v-model="form.sfcCode" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
+        </el-form-item>
+        <el-form-item label="浜у搧缂栧彿" prop="productCode">
+          <el-input v-model="form.productCode" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
+        </el-form-item>
+        <el-form-item label="浜х嚎缂栧彿" prop="productionLine">
+          <el-input v-model="form.productionLine" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
+        </el-form-item>
+        <el-form-item label="宸ヤ綅缂栧彿" prop="locationCode">
+          <el-input v-model="form.locationCode" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
+        </el-form-item>
+        <el-form-item label="璁惧缂栧彿" prop="equipmentNo">
+          <el-input v-model="form.equipmentNo" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
+        </el-form-item>
+        <el-form-item label="鍙傛暟缂栫爜" prop="paramCode">
+          <el-input v-model="form.paramCode" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
+        </el-form-item>
+        <el-form-item label="鍙傛暟鍊�" prop="paramValue">
+          <el-input v-model="form.paramValue" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
+        </el-form-item>
+        <el-form-item label="鍙傛暟涓婇檺" prop="paramUpper">
+          <el-input v-model="form.paramUpper" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
+        </el-form-item>
+        <el-form-item label="鍙傛暟涓嬮檺" prop="paramLower">
+          <el-input v-model="form.paramLower" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
+        </el-form-item>
+        <el-form-item label="鏍囧噯鍊�" prop="paramStandard">
+          <el-input v-model="form.paramStandard" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
+        </el-form-item>
+        <el-form-item label="鐘舵��" prop="state">
+          <el-input v-model="form.state" placeholder="璇疯緭鍏ョ姸鎬�" />
+        </el-form-item>
+        <el-form-item label="鍙傛暟鍚嶇О" prop="paramName">
+          <el-input v-model="form.paramName" placeholder="璇疯緭鍏ュ弬鏁板悕绉�" />
+        </el-form-item>
+        <el-form-item label="鍗曚綅" prop="unit">
+          <el-input v-model="form.unit" placeholder="璇疯緭鍏ュ崟浣�" />
+        </el-form-item>
+        <el-form-item label="绫诲瀷" prop="type">
+          <el-select v-model="form.type" placeholder="璇烽�夋嫨绫诲瀷">
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listParamCollection, getParamCollection, delParamCollection, addParamCollection, updateParamCollection } from "@/api/main/da/paramCollection/paramCollection";
+
+export default {
+  name: "ParamCollection",
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 璁惧浜у搧杩囩▼鍙傛暟閲囬泦琛ㄦ牸鏁版嵁
+      paramCollectionList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        workOrderNo: null,
+        sfcCode: null,
+        productCode: null,
+        productionLine: null,
+        locationCode: null,
+        equipmentNo: null,
+        paramCode: null,
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        id: [
+          { required: true, message: "涓婚敭id涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        workOrderNo: [
+          { required: true, message: "宸ュ崟缂栧彿涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        sfcCode: [
+          { required: true, message: "鎬绘垚搴忓垪鍙蜂笉鑳戒负绌�", trigger: "blur" }
+        ],
+        productCode: [
+          { required: true, message: "浜у搧缂栧彿涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        productionLine: [
+          { required: true, message: "浜х嚎缂栧彿涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        locationCode: [
+          { required: true, message: "宸ヤ綅缂栧彿涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        paramCode: [
+          { required: true, message: "鍙傛暟缂栫爜涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        paramValue: [
+          { required: true, message: "鍙傛暟鍊间笉鑳戒负绌�", trigger: "blur" }
+        ],
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 鏌ヨ璁惧浜у搧杩囩▼鍙傛暟閲囬泦鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listParamCollection(this.queryParams).then(response => {
+        this.paramCollectionList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        id: null,
+        workOrderNo: null,
+        sfcCode: null,
+        productCode: null,
+        productionLine: null,
+        locationCode: null,
+        equipmentNo: null,
+        paramCode: null,
+        paramValue: null,
+        paramUpper: null,
+        paramLower: null,
+        paramStandard: null,
+        collectionTime: null,
+        spareField1: null,
+        spareField2: null,
+        createUser: null,
+        createTime: null,
+        updateUser: null,
+        updateTime: null,
+        state: null,
+        paramName: null,
+        unit: null,
+        type: null
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "娣诲姞璁惧浜у搧杩囩▼鍙傛暟閲囬泦";
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getParamCollection(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "淇敼璁惧浜у搧杩囩▼鍙傛暟閲囬泦";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateParamCollection(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addParamCollection(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎璁惧浜у搧杩囩▼鍙傛暟閲囬泦缂栧彿涓�"' + ids + '"鐨勬暟鎹」锛�').then(function() {
+        return delParamCollection(ids);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('main/paramCollection/export', {
+        ...this.queryParams
+      }, `paramCollection_${new Date().getTime()}.xlsx`)
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/main/da/passingStationCollection/index.vue b/jcdm-ui/src/views/main/da/passingStationCollection/index.vue
new file mode 100644
index 0000000..9918df7
--- /dev/null
+++ b/jcdm-ui/src/views/main/da/passingStationCollection/index.vue
@@ -0,0 +1,370 @@
+<template>
+  <div class="app-container">
+    <el-card class="box-card">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="鍏ョ珯鏃堕棿" prop="inboundTime">
+        <el-date-picker clearable
+          v-model="queryParams.inboundTime"
+          type="date"
+          value-format="yyyy-MM-dd"
+          placeholder="璇烽�夋嫨鍏ョ珯鏃堕棿">
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item label="鍑虹珯鏃堕棿" prop="outboundTime">
+        <el-date-picker clearable
+          v-model="queryParams.outboundTime"
+          type="date"
+          value-format="yyyy-MM-dd"
+          placeholder="璇烽�夋嫨鍑虹珯鏃堕棿">
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item style="float: right">
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+    </el-card>
+    <el-card style="margin-top: 10px" class="box-card">
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['da:passingStationCollection:add']"
+        >鏂板</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['da:passingStationCollection:edit']"
+        >淇敼</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['da:passingStationCollection:remove']"
+        >鍒犻櫎</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['da:passingStationCollection:export']"
+        >瀵煎嚭</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" border :data="passingStationCollectionList" @selection-change="handleSelectionChange" v-if="passingStationCollectionList.length > 0">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="宸ュ崟缂栧彿" align="center" prop="workOrderNo">
+      </el-table-column>
+      <el-table-column label="鎬绘垚搴忓垪鍙�" align="center" prop="sfcCode">
+      </el-table-column>
+      <el-table-column label="浜у搧缂栧彿" align="center" prop="productCode">
+      </el-table-column>
+      <el-table-column label="浜х嚎缂栧彿" align="center" prop="productionLine">
+      </el-table-column>
+      <el-table-column label="宸ヤ綅缂栧彿" align="center" prop="locationCode">
+      </el-table-column>
+      <el-table-column label="鍏ョ珯鏃堕棿" align="center" prop="inboundTime" width="100">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.inboundTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="鍑虹珯鏃堕棿" align="center" prop="outboundTime" width="100">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.outboundTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
+        </template>
+      </el-table-column>
+
+      <el-table-column label="鏄惁鍚堟牸" align="center" prop="outRsSign">
+      </el-table-column>
+      <el-table-column label="NG鍘熷洜" align="center" prop="outMsgSign">
+      </el-table-column>
+      <el-table-column label="閲囬泦鏃堕棿" align="center" prop="collectionTime" width="180">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.collectionTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="鑺傛媿鏃堕棿" align="center" prop="beatTime">
+      </el-table-column>
+      <el-table-column fixed="right" label="鎿嶄綔" width="200" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="success"
+            plain
+            style="width: 72px"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['da:passingStationCollection:edit']"
+          >淇敼</el-button>
+          <el-button
+            size="mini"
+            type="danger"
+            plain
+            style="width: 72px"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['da:passingStationCollection:remove']"
+          >鍒犻櫎</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+      <el-empty v-else>
+        <span slot="description">鏆傛棤鏁版嵁</span>
+      </el-empty>
+    </el-card>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 娣诲姞鎴栦慨鏀逛骇鍝佽繃绔欓噰闆嗗璇濇 -->
+    <el-dialog v-dialogpop-up :title="title" :visible.sync="open" width="1000px" append-to-body>
+      <el-form ref="form" inline :model="form" :rules="rules" label-width="120px">
+        <el-form-item label="宸ュ崟缂栧彿" prop="workOrderNo">
+          <el-input v-model="form.workOrderNo" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
+        </el-form-item>
+        <el-form-item label="鎬绘垚搴忓垪鍙�" prop="sfcCode">
+          <el-input v-model="form.sfcCode" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
+        </el-form-item>
+        <el-form-item label="浜у搧缂栧彿" prop="productCode">
+          <el-input v-model="form.productCode" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
+        </el-form-item>
+        <el-form-item label="浜х嚎缂栧彿" prop="productionLine">
+          <el-input v-model="form.productionLine" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
+        </el-form-item>
+        <el-form-item label="宸ヤ綅缂栧彿" prop="locationCode">
+          <el-input v-model="form.locationCode" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
+        </el-form-item>
+        <el-form-item label="璁惧缂栧彿" prop="equipmentNo">
+          <el-input v-model="form.equipmentNo" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
+        </el-form-item>
+        <el-form-item label="鍏ョ珯鏃堕棿" prop="inboundTime">
+          <el-date-picker clearable
+            v-model="form.inboundTime"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="璇烽�夋嫨鍏ョ珯鏃堕棿">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="鍑虹珯鏃堕棿" prop="outboundTime">
+          <el-date-picker clearable
+            v-model="form.outboundTime"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="璇烽�夋嫨鍑虹珯鏃堕棿">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="鏄惁鍚堟牸" prop="outRsSign">
+          <el-input v-model="form.outRsSign" placeholder="璇疯緭鍏ュ嚭绔欐槸鍚﹀悎鏍�" />
+        </el-form-item>
+        <el-form-item label="NG鍘熷洜" prop="outMsgSign">
+          <el-input v-model="form.outMsgSign" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
+        </el-form-item>
+        <el-form-item label="閲囬泦鏃堕棿" prop="collectionTime">
+          <el-date-picker clearable
+            v-model="form.collectionTime"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="璇烽�夋嫨閲囬泦鏃堕棿">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="鑺傛媿鏃堕棿" prop="beatTime">
+          <el-input v-model="form.beatTime" placeholder="璇疯緭鍏ヨ妭鎷嶆椂闂�" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listPassingStationCollection, getPassingStationCollection, delPassingStationCollection, addPassingStationCollection, updatePassingStationCollection } from "@/api/main/da/passingStationCollection/passingStationCollection";
+
+export default {
+  name: "PassingStationCollection",
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 浜у搧杩囩珯閲囬泦琛ㄦ牸鏁版嵁
+      passingStationCollectionList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        workOrderNo: null,
+        sfcCode: null,
+        productCode: null,
+        productionLine: null,
+        locationCode: null,
+        equipmentNo: null,
+        inboundTime: null,
+        outboundTime: null,
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        id: [
+          { required: true, message: "涓婚敭id涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 鏌ヨ浜у搧杩囩珯閲囬泦鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listPassingStationCollection(this.queryParams).then(response => {
+        this.passingStationCollectionList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        id: null,
+        workOrderNo: null,
+        sfcCode: null,
+        productCode: null,
+        productionLine: null,
+        locationCode: null,
+        equipmentNo: null,
+        inboundTime: null,
+        outboundTime: null,
+        inRsSign: null,
+        inMsgSign: null,
+        outRsSign: null,
+        outMsgSign: null,
+        collectionTime: null,
+        spareField1: null,
+        spareField2: null,
+        createUser: null,
+        createTime: null,
+        updateUser: null,
+        updateTime: null,
+        beatTime: null
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "娣诲姞浜у搧杩囩珯閲囬泦";
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getPassingStationCollection(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "淇敼浜у搧杩囩珯閲囬泦";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updatePassingStationCollection(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addPassingStationCollection(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎浜у搧杩囩珯閲囬泦缂栧彿涓�"' + ids + '"鐨勬暟鎹」锛�').then(function() {
+        return delPassingStationCollection(ids);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('da/passingStationCollection/export', {
+        ...this.queryParams
+      }, `passingStationCollection_${new Date().getTime()}.xlsx`)
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/main/em/equipmentAlarm/index.vue b/jcdm-ui/src/views/main/em/equipmentAlarm/index.vue
new file mode 100644
index 0000000..b8d9eca
--- /dev/null
+++ b/jcdm-ui/src/views/main/em/equipmentAlarm/index.vue
@@ -0,0 +1,377 @@
+<template>
+  <div class="app-container">
+    <el-card class="box-card">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="璁惧缂栧彿" prop="equipmentCode">
+        <el-input
+          v-model="queryParams.equipmentCode"
+          placeholder="璇疯緭鍏ヨ澶囩紪鍙�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="璁惧鍚嶇О" prop="equipmentName">
+        <el-input
+          v-model="queryParams.equipmentName"
+          placeholder="璇疯緭鍏ヨ澶囧悕绉�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+<!--      <el-form-item label="璁惧绫诲瀷" prop="equipmentType">-->
+<!--        <el-select v-model="queryParams.equipmentType" placeholder="璇烽�夋嫨璁惧绫诲瀷" clearable>-->
+<!--          <el-option-->
+<!--            v-for="dict in dict.type.${dictType}"-->
+<!--            :key="dict.value"-->
+<!--            :label="dict.label"-->
+<!--            :value="dict.value"-->
+<!--          />-->
+<!--        </el-select>-->
+<!--      </el-form-item>-->
+      <el-form-item label="鏁呴殰浠g爜" prop="errorNo">
+        <el-input
+          v-model="queryParams.errorNo"
+          placeholder="璇疯緭鍏ユ晠闅滀唬鐮�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item style="float: right">
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+    </el-card>
+    <el-card style="margin-top: 10px" class="box-card">
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['em:equipmentAlarm:add']"
+        >鏂板</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['em:equipmentAlarm:edit']"
+        >淇敼</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['em:equipmentAlarm:remove']"
+        >鍒犻櫎</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['em:equipmentAlarm:export']"
+        >瀵煎嚭</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table border v-loading="loading" :data="equipmentAlarmList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="璁惧缂栧彿" width="120" align="center" prop="equipmentCode">
+      </el-table-column>
+      <el-table-column label="璁惧鍚嶇О" width="150" align="center" prop="equipmentName">
+      </el-table-column>
+      <el-table-column label="璁惧绫诲瀷" align="center" prop="equipmentType">
+      </el-table-column>
+      <el-table-column label="杞﹂棿缂栧彿" width="80" align="center" prop="workshopCode">
+      </el-table-column>
+      <el-table-column label="浜х嚎缂栧彿" width="80" align="center" prop="lineCode">
+      </el-table-column>
+      <el-table-column label="宸ュ簭缂栧彿" align="center" prop="processesCode">
+      </el-table-column>
+      <el-table-column label="鏁呴殰浠g爜" width="100" align="center" prop="errorNo">
+      </el-table-column>
+      <el-table-column label="鏁呴殰鎻忚堪" width="160" align="center" prop="errorDesc">
+      </el-table-column>
+      <el-table-column label="鎶ヨ鏃堕棿" width="160" align="center" prop="alarmTime">
+      </el-table-column>
+      <el-table-column label="鏄惁鎭㈠" align="center" prop="whetherRecovery">
+      </el-table-column>
+      <el-table-column label="鎭㈠鏃堕棿" width="160" align="center" prop="recoveryTime">
+      </el-table-column>
+      <el-table-column label="澶囨敞" align="center" prop="remarks">
+      </el-table-column>
+      <el-table-column fixed="right" width="200" label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            plain
+            type="success"
+            style="width: 72px"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['em:equipmentAlarm:edit']"
+          >淇敼</el-button>
+          <el-button
+            size="mini"
+            plain
+            type="danger"
+            style="width: 72px"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['em:equipmentAlarm:remove']"
+          >鍒犻櫎</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    </el-card>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 娣诲姞鎴栦慨鏀硅澶囨姤璀﹀璇濇 -->
+    <el-dialog v-dialogpop-up :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="璁惧缂栧彿" prop="equipmentCode">
+          <el-input v-model="form.equipmentCode" placeholder="璇疯緭鍏ヨ澶囩紪鍙�" />
+        </el-form-item>
+        <el-form-item label="璁惧鍚嶇О" prop="equipmentName">
+          <el-input v-model="form.equipmentName" placeholder="璇疯緭鍏ヨ澶囧悕绉�" />
+        </el-form-item>
+<!--        <el-form-item label="璁惧绫诲瀷" prop="equipmentType">-->
+<!--          <el-select v-model="form.equipmentType" placeholder="璇烽�夋嫨璁惧绫诲瀷">-->
+<!--            <el-option-->
+<!--              v-for="dict in dict.type.${dictType}"-->
+<!--              :key="dict.value"-->
+<!--              :label="dict.label"-->
+<!--              :value="dict.value"-->
+<!--            ></el-option>-->
+<!--          </el-select>-->
+<!--        </el-form-item>-->
+        <el-form-item label="杞﹂棿缂栧彿" prop="workshopCode">
+          <el-input v-model="form.workshopCode" placeholder="璇疯緭鍏ヨ溅闂寸紪鍙�" />
+        </el-form-item>
+        <el-form-item label="浜х嚎缂栧彿" prop="lineCode">
+          <el-input v-model="form.lineCode" placeholder="璇疯緭鍏ヤ骇绾跨紪鍙�" />
+        </el-form-item>
+<!--        <el-form-item label="宸ュ簭缂栧彿" prop="processesCode">-->
+<!--          <el-select v-model="form.processesCode" placeholder="璇烽�夋嫨宸ュ簭缂栧彿">-->
+<!--            <el-option-->
+<!--              v-for="dict in dict.type.${dictType}"-->
+<!--              :key="dict.value"-->
+<!--              :label="dict.label"-->
+<!--              :value="dict.value"-->
+<!--            ></el-option>-->
+<!--          </el-select>-->
+<!--        </el-form-item>-->
+        <el-form-item label="鏁呴殰浠g爜" prop="errorNo">
+          <el-input v-model="form.errorNo" placeholder="璇疯緭鍏ユ晠闅滀唬鐮�" />
+        </el-form-item>
+        <el-form-item label="鏁呴殰鎻忚堪" prop="errorDesc">
+          <el-input v-model="form.errorDesc" placeholder="璇疯緭鍏ユ晠闅滄弿杩�" />
+        </el-form-item>
+        <el-form-item label="鏄惁鎭㈠" prop="whetherRecovery">
+          <el-input v-model="form.whetherRecovery" placeholder="璇疯緭鍏ユ槸鍚︽仮澶�(0鍚�1鏄�)" />
+        </el-form-item>
+        <el-form-item label="澶囨敞" prop="remarks">
+          <el-input v-model="form.remarks" placeholder="璇疯緭鍏ュ娉�" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listEquipmentAlarm, getEquipmentAlarm, delEquipmentAlarm, addEquipmentAlarm, updateEquipmentAlarm } from "@/api/main/em/equipmentAlarm/equipmentAlarm";
+
+export default {
+  name: "EquipmentAlarm",
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 璁惧鎶ヨ琛ㄦ牸鏁版嵁
+      equipmentAlarmList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        equipmentCode: null,
+        equipmentName: null,
+        equipmentType: null,
+        errorNo: null,
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        id: [
+          { required: true, message: "ID涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        equipmentCode: [
+          { required: true, message: "璁惧缂栧彿涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        equipmentName: [
+          { required: true, message: "璁惧鍚嶇О涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        equipmentType: [
+          { required: true, message: "璁惧绫诲瀷涓嶈兘涓虹┖", trigger: "change" }
+        ],
+        processesCode: [
+          { required: true, message: "宸ュ簭缂栧彿涓嶈兘涓虹┖", trigger: "change" }
+        ],
+        errorNo: [
+          { required: true, message: "鏁呴殰浠g爜涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 鏌ヨ璁惧鎶ヨ鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listEquipmentAlarm(this.queryParams).then(response => {
+        this.equipmentAlarmList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        id: null,
+        equipmentCode: null,
+        equipmentName: null,
+        equipmentType: null,
+        workshopCode: null,
+        lineCode: null,
+        processesCode: null,
+        errorNo: null,
+        errorDesc: null,
+        alarmTime: null,
+        whetherRecovery: null,
+        recoveryTime: null,
+        spareField1: null,
+        spareField2: null,
+        spareField3: null,
+        spareField4: null,
+        remarks: null
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "娣诲姞璁惧鎶ヨ";
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getEquipmentAlarm(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "淇敼璁惧鎶ヨ";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateEquipmentAlarm(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addEquipmentAlarm(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎璁惧鎶ヨ缂栧彿涓�"' + ids + '"鐨勬暟鎹」锛�').then(function() {
+        return delEquipmentAlarm(ids);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('em/equipmentAlarm/export', {
+        ...this.queryParams
+      }, `equipmentAlarm_${new Date().getTime()}.xlsx`)
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/main/em/equipmentArchives/index.vue b/jcdm-ui/src/views/main/em/equipmentArchives/index.vue
new file mode 100644
index 0000000..e7977d4
--- /dev/null
+++ b/jcdm-ui/src/views/main/em/equipmentArchives/index.vue
@@ -0,0 +1,436 @@
+<template>
+  <div class="app-container">
+    <el-card class="box-card">
+        <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+          <el-form-item label="璁惧缂栫爜" prop="equipmentCode">
+            <el-input
+              v-model="queryParams.equipmentCode"
+              placeholder="璇疯緭鍏ヨ澶囩紪鐮�"
+              clearable
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item label="璁惧鍚嶇О" prop="equipmentName">
+            <el-input
+              v-model="queryParams.equipmentName"
+              placeholder="璇疯緭鍏ヨ澶囧悕绉�"
+              clearable
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item label="鐘舵��" prop="status">
+            <el-select v-model="queryParams.status" placeholder="璇烽�夋嫨鐘舵��" clearable>
+              <el-option
+                v-for="dict in dict.type.sys_normal_disable"
+                :key="dict.value"
+                :label="dict.label"
+                :value="dict.value"
+              />
+            </el-select>
+          </el-form-item>
+          <el-form-item style="float: right">
+            <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+            <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+          </el-form-item>
+        </el-form>
+    </el-card>
+
+    <el-card style="margin-top: 10px" class="box-card">
+        <el-row :gutter="10" class="mb8">
+          <el-col :span="1.5">
+            <el-button
+              type="primary"
+              plain
+              icon="el-icon-plus"
+              size="mini"
+              @click="handleAdd"
+              v-hasPermi="['em:equipmentArchives:add']"
+            >鏂板</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="success"
+              plain
+              icon="el-icon-edit"
+              size="mini"
+              :disabled="single"
+              @click="handleUpdate"
+              v-hasPermi="['em:equipmentArchives:edit']"
+            >淇敼</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="danger"
+              plain
+              icon="el-icon-delete"
+              size="mini"
+              :disabled="multiple"
+              @click="handleDelete"
+              v-hasPermi="['em:equipmentArchives:remove']"
+            >鍒犻櫎</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="warning"
+              plain
+              icon="el-icon-download"
+              size="mini"
+              @click="handleExport"
+              v-hasPermi="['em:equipmentArchives:export']"
+            >瀵煎嚭</el-button>
+          </el-col>
+          <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+        </el-row>
+
+        <el-table border v-loading="loading" :data="equipmentArchivesList" @selection-change="handleSelectionChange">
+          <el-table-column type="selection" width="55" align="center" />
+          <el-table-column label="璁惧缂栫爜" align="center" prop="equipmentCode"/>
+          <el-table-column label="璁惧鍚嶇О" align="center" prop="equipmentName"/>
+          <el-table-column label="鐘舵��" align="center" prop="status" width="80">
+            <template slot-scope="scope">
+              <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
+            </template>
+          </el-table-column>
+          <el-table-column label="宸ュ簭缂栧彿" align="center" prop="processesCode"/>
+          <el-table-column label="鍝佺墝" align="center" prop="equipmentBrand"/>
+          <el-table-column label="瑙勬牸鍨嬪彿" align="center" prop="equipmentSpec"/>
+          <el-table-column label="杞﹂棿缂栫爜" align="center" prop="workshopCode"/>
+          <el-table-column label="浜х嚎缂栫爜" align="center" prop="lineCode"/>
+          <el-table-column label="璁惧鐘舵��" align="center" prop="status"/>
+          <el-table-column label="鍒涘缓鏃堕棿" width="160" align="center" prop="createTime"/>
+          <el-table-column fixed="right" width="200" label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+            <template slot-scope="scope">
+              <el-button
+                size="mini"
+                type="success"
+                plain
+                style="width: 72px"
+                icon="el-icon-edit"
+                @click="handleUpdate(scope.row)"
+                v-hasPermi="['em:equipmentArchives:edit']"
+              >淇敼</el-button>
+              <el-button
+                size="mini"
+                type="danger"
+                plain
+                style="width: 72px"
+                icon="el-icon-delete"
+                @click="handleDelete(scope.row)"
+                v-hasPermi="['em:equipmentArchives:remove']"
+              >鍒犻櫎</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+    </el-card>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 娣诲姞鎴栦慨鏀硅澶囨。妗堝璇濇 -->
+    <el-dialog v-dialogpop-up :title="title" :visible.sync="open" width="500px" append-to-body>
+      <span slot="title">
+        <i class="el-icon-s-order"></i>
+        {{titleName}}
+      </span>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="璁惧缂栫爜" prop="equipmentCode">
+          <el-input v-model="form.equipmentCode" placeholder="璇疯緭鍏ヨ澶囩紪鐮�" />
+        </el-form-item>
+        <el-form-item label="璁惧鍚嶇О" prop="equipmentName">
+          <el-input v-model="form.equipmentName" placeholder="璇疯緭鍏ヨ澶囧悕绉�" />
+        </el-form-item>
+        <el-form-item label="鐘舵��" prop="status">
+          <el-radio-group v-model="form.status">
+            <el-radio
+              v-for="dict in dict.type.sys_normal_disable"
+              :key="dict.value"
+              :label="dict.value"
+            >{{dict.label}}</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="宸ュ簭缂栧彿" prop="processesCode">
+          <el-select style="width: 100%" @change="handleSelectChangeprocessesCode(form.processesCode)" v-model="form.processesCode" placeholder="璇烽�夋嫨宸ュ簭缂栧彿">
+            <el-option
+              v-for="item in processesCodeoptions"
+              :key="item.index"
+              :label="item.processesCode"
+              :value="item.processesCode">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="鍝佺墝" prop="equipmentBrand">
+          <el-input v-model="form.equipmentBrand" placeholder="璇疯緭鍏ュ搧鐗�" />
+        </el-form-item>
+        <el-form-item label="璁惧绫诲瀷" prop="equipmentTypeName">
+          <el-input v-model="form.equipmentTypeName" placeholder="璇疯緭鍏ヨ澶囩被鍨嬪悕绉�" />
+        </el-form-item>
+        <el-form-item label="瑙勬牸鍨嬪彿" prop="equipmentSpec">
+          <el-input v-model="form.equipmentSpec" placeholder="璇疯緭鍏ヨ鏍煎瀷鍙�" />
+        </el-form-item>
+        <el-form-item label="杞﹂棿缂栧彿" prop="workshopCode">
+          <el-select style="width: 100%" @change="handleSelectChange(form.workshopCode)" v-model="form.workshopCode" placeholder="璇烽�夋嫨杞﹂棿缂栧彿">
+            <el-option
+              v-for="item in options"
+              :key="item.workshopCode"
+              :label="item.workshopName"
+              :value="item.workshopCode">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item  label="浜х嚎缂栧彿" prop="lineCode">
+          <el-select style="width: 100%" v-model="form.lineCode" placeholder="璇烽�夋嫨浜х嚎缂栧彿">
+            <el-option
+              v-for="item in lineOptions"
+              :key="item.lineCode"
+              :label="item.lineName"
+              :value="item.lineCode">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="澶囨敞" prop="remark">
+          <el-input v-model="form.remark" placeholder="璇疯緭鍏ュ娉�" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listEquipmentArchives, getEquipmentArchives, delEquipmentArchives, addEquipmentArchives, updateEquipmentArchives } from "@/api/main/em/equipmentArchives/equipmentArchives";
+import {listWorkshop} from "@/api/main/bs/workshop/workshop";
+import {listLineInfo} from "@/api/main/bs/lineInfo/lineInfo";
+import ItemSelect  from "@/components/itemSelect/single.vue";
+import {listProductionOrde} from "@/api/main/om/productionOrde/productionOrde";
+import {listProcesses} from "@/api/main/bs/processes/processes";
+
+export default {
+  name: "EquipmentArchives",
+  dicts: ['sys_normal_disable'],
+  components: {
+    ItemSelect ,
+  },
+  data() {
+    return {
+      // 閬僵灞�
+      lineOptions: [],
+      processesCodeoptions:[],
+      options: [],
+      loading: true,
+      titleName: "",
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 璁惧妗f琛ㄦ牸鏁版嵁
+      equipmentArchivesList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        equipmentCode: null,
+        equipmentName: null,
+        equipmentBrand: null,
+        equipmentSpec: null,
+        equipmentTypeId: null,
+        equipmentTypeCode: null,
+        equipmentTypeName: null,
+        workshopCode: null,
+        lineCode: null,
+        processesCode: null,
+        status: null,
+        createUser: null,
+        updateUser: null,
+        spareField1: null,
+        spareField2: null,
+        spareField3: null,
+        spareField4: null
+      },
+      processesCodeQueryParams:{
+        pageNum: 1,
+        pageSize: 10,
+        processesCodes: null,
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        id: [
+          { required: true, message: "ID涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        equipmentCode: [
+          { required: true, message: "璁惧缂栫爜涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        equipmentName: [
+          { required: true, message: "璁惧鍚嶇О涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        equipmentTypeId: [
+          { required: true, message: "璁惧绫诲瀷ID涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+      }
+    };
+  },
+  created() {
+    this.getList();
+    this.initWorkshop();
+    this.initProcesses();
+
+  },
+  methods: {
+    /** 鏌ヨ璁惧妗f鍒楄〃 */
+    initWorkshop(){
+      listWorkshop().then(response => {
+        this.options = response.rows;
+      });
+    },
+    // 鍦ㄨ繖閲岀紪鍐欏鐞嗛�変腑浜嬩欢鐨勯�昏緫
+    handleSelectChange(selectedOption) {
+      this.form.lineCode = null;
+      let param = {
+        workshopCode : selectedOption
+      }
+      listLineInfo(param).then(response => {
+        this.lineOptions = response.rows;
+      });
+    },
+    handleSelectChangeprocessesCode(selectedOption) {
+      this.processesCodeQueryParams.processesCodes = selectedOption;
+      listProcesses(this.queryParams).then(response => {
+        this.form.processesName = response.rows[0].processesName;
+      });
+    },
+    initProcesses(){
+      listProcesses(this.queryParams).then(response => {
+        this.processesCodeoptions = response.rows;
+      });
+    },
+    getList() {
+      console.log(this.queryParams)
+      this.loading = true;
+      listEquipmentArchives(this.queryParams).then(response => {
+        this.equipmentArchivesList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        id: null,
+        equipmentCode: null,
+        equipmentName: null,
+        equipmentBrand: null,
+        equipmentSpec: null,
+        equipmentTypeId: null,
+        equipmentTypeCode: null,
+        equipmentTypeName: null,
+        workshopCode: null,
+        lineCode: null,
+        processesCode: null,
+        status: "0",
+        remark: null,
+        createUser: null,
+        createTime: null,
+        updateUser: null,
+        updateTime: null,
+        spareField1: null,
+        spareField2: null,
+        spareField3: null,
+        spareField4: null
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.titleName = "娣诲姞璁惧妗f";
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getEquipmentArchives(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.titleName = "淇敼璁惧妗f";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateEquipmentArchives(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addEquipmentArchives(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎璁惧妗f缂栧彿涓�"' + ids + '"鐨勬暟鎹」锛�').then(function() {
+        return delEquipmentArchives(ids);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('em/equipmentArchives/export', {
+        ...this.queryParams
+      }, `equipmentArchives_${new Date().getTime()}.xlsx`)
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/main/em/equipmentStatus/index.vue b/jcdm-ui/src/views/main/em/equipmentStatus/index.vue
new file mode 100644
index 0000000..b0bd3d6
--- /dev/null
+++ b/jcdm-ui/src/views/main/em/equipmentStatus/index.vue
@@ -0,0 +1,356 @@
+<template>
+  <div class="app-container">
+    <el-card class="box-card">
+        <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+          <el-form-item label="璁惧缂栧彿" prop="equipmentNo">
+            <el-input
+              v-model="queryParams.equipmentNo"
+              placeholder="璇疯緭鍏ヨ澶囩紪鍙�"
+              clearable
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item label="璁惧鍚嶇О" prop="equipmentName">
+            <el-input
+              v-model="queryParams.equipmentName"
+              placeholder="璇疯緭鍏ヨ澶囧悕绉�"
+              clearable
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+<!--          <el-form-item label="杞﹂棿缂栧彿" prop="workshopCode">-->
+<!--            <el-input-->
+<!--              v-model="queryParams.workshopCode"-->
+<!--              placeholder="璇疯緭鍏ヨ溅闂寸紪鍙�"-->
+<!--              clearable-->
+<!--              @keyup.enter.native="handleQuery"-->
+<!--            />-->
+<!--          </el-form-item>-->
+<!--          <el-form-item label="浜х嚎缂栧彿" prop="productionLineCode">-->
+<!--            <el-input-->
+<!--              v-model="queryParams.productionLineCode"-->
+<!--              placeholder="璇疯緭鍏ヤ骇绾跨紪鍙�"-->
+<!--              clearable-->
+<!--              @keyup.enter.native="handleQuery"-->
+<!--            />-->
+<!--          </el-form-item>-->
+          <el-form-item label="宸ュ簭缂栧彿" prop="processesCode">
+            <el-input
+              v-model="queryParams.processesCode"
+              placeholder="璇疯緭鍏ュ伐搴忕紪鍙�"
+              clearable
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+<!--          <el-form-item label="璁惧鐘舵��(1杩愯浆2寰呮満3鏁呴殰)" prop="eqStatus">-->
+<!--            <el-select v-model="queryParams.eqStatus" placeholder="璇烽�夋嫨璁惧鐘舵��(1杩愯浆2寰呮満3鏁呴殰)" clearable>-->
+<!--              <el-option-->
+<!--                v-for="dict in dict.type.${dictType}"-->
+<!--                :key="dict.value"-->
+<!--                :label="dict.label"-->
+<!--                :value="dict.value"-->
+<!--              />-->
+<!--            </el-select>-->
+<!--          </el-form-item>-->
+          <el-form-item style="float: right">
+            <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+            <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+          </el-form-item>
+        </el-form>
+    </el-card>
+
+    <el-card style="margin-top: 10px" class="box-card">
+        <el-row :gutter="10" class="mb8">
+          <el-col :span="1.5">
+            <el-button
+              type="primary"
+              plain
+              icon="el-icon-plus"
+              size="mini"
+              @click="handleAdd"
+              v-hasPermi="['em:equipmentStatus:add']"
+            >鏂板</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="success"
+              plain
+              icon="el-icon-edit"
+              size="mini"
+              :disabled="single"
+              @click="handleUpdate"
+              v-hasPermi="['em:equipmentStatus:edit']"
+            >淇敼</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="danger"
+              plain
+              icon="el-icon-delete"
+              size="mini"
+              :disabled="multiple"
+              @click="handleDelete"
+              v-hasPermi="['em:equipmentStatus:remove']"
+            >鍒犻櫎</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="warning"
+              plain
+              icon="el-icon-download"
+              size="mini"
+              @click="handleExport"
+              v-hasPermi="['em:equipmentStatus:export']"
+            >瀵煎嚭</el-button>
+          </el-col>
+          <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+        </el-row>
+
+        <el-table border v-loading="loading" :data="equipmentStatusList" @selection-change="handleSelectionChange">
+          <el-table-column type="selection" width="55" align="center" />
+          <el-table-column label="ID" align="center" prop="id" />
+          <el-table-column label="璁惧缂栧彿" align="center" prop="equipmentNo">
+          </el-table-column>
+          <el-table-column label="璁惧鍚嶇О" align="center" prop="equipmentName">
+          </el-table-column>
+          <el-table-column label="杞﹂棿缂栧彿" align="center" prop="workshopCode">
+          </el-table-column>
+          <el-table-column label="浜х嚎缂栧彿" align="center" prop="productionLineCode">
+          </el-table-column>
+          <el-table-column label="宸ュ簭缂栧彿" align="center" prop="processesCode">
+          </el-table-column>
+          <el-table-column label="璁惧鐘舵��(1杩愯浆2寰呮満3鏁呴殰)" align="center" prop="eqStatus">
+          </el-table-column>
+          <el-table-column label="澶囨敞" align="center" prop="remarks">
+          </el-table-column>
+          <el-table-column label="鏇存柊鏃堕棿" align="center" prop="updateTime">
+          </el-table-column>
+          <el-table-column fixed="right" width="200" label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+            <template slot-scope="scope">
+              <el-button
+                size="mini"
+                type="success"
+                plain
+                style="width: 72px"
+                icon="el-icon-edit"
+                @click="handleUpdate(scope.row)"
+                v-hasPermi="['em:equipmentStatus:edit']"
+              >淇敼</el-button>
+              <el-button
+                size="mini"
+                type="danger"
+                plain
+                style="width: 72px"
+                icon="el-icon-delete"
+                @click="handleDelete(scope.row)"
+                v-hasPermi="['em:equipmentStatus:remove']"
+              >鍒犻櫎</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+    </el-card>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 娣诲姞鎴栦慨鏀硅澶囩姸鎬佸璇濇 -->
+    <el-dialog v-dialogpop-up :title="title" :visible.sync="open" width="500px" append-to-body>
+      <span slot="title">
+        <i class="el-icon-s-order"></i>
+        {{titleName}}
+      </span>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="璁惧缂栧彿" prop="equipmentNo">
+          <el-input v-model="form.equipmentNo" placeholder="璇疯緭鍏ヨ澶囩紪鍙�" />
+        </el-form-item>
+        <el-form-item label="璁惧鍚嶇О" prop="equipmentName">
+          <el-input v-model="form.equipmentName" placeholder="璇疯緭鍏ヨ澶囧悕绉�" />
+        </el-form-item>
+        <el-form-item label="杞﹂棿缂栧彿" prop="workshopCode">
+          <el-input v-model="form.workshopCode" placeholder="璇疯緭鍏ヨ溅闂寸紪鍙�" />
+        </el-form-item>
+        <el-form-item label="浜х嚎缂栧彿" prop="productionLineCode">
+          <el-input v-model="form.productionLineCode" placeholder="璇疯緭鍏ヤ骇绾跨紪鍙�" />
+        </el-form-item>
+        <el-form-item label="宸ュ簭缂栧彿" prop="processesCode">
+          <el-input v-model="form.processesCode" placeholder="璇疯緭鍏ュ伐搴忕紪鍙�" />
+        </el-form-item>
+<!--        <el-form-item label="璁惧鐘舵��(1杩愯浆2寰呮満3鏁呴殰)" prop="eqStatus">-->
+<!--          <el-radio-group v-model="form.eqStatus">-->
+<!--            <el-radio-->
+<!--              v-for="dict in dict.type.${dictType}"-->
+<!--              :key="dict.value"-->
+<!--              :label="dict.value"-->
+<!--            >{{dict.label}}</el-radio>-->
+<!--          </el-radio-group>-->
+<!--        </el-form-item>-->
+        <el-form-item label="澶囨敞" prop="remarks">
+          <el-input v-model="form.remarks" placeholder="璇疯緭鍏ュ娉�" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listEquipmentStatus, getEquipmentStatus, delEquipmentStatus, addEquipmentStatus, updateEquipmentStatus } from "@/api/main/em/equipmentStatus/equipmentStatus";
+
+export default {
+  name: "EquipmentStatus",
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      titleName: "",
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 璁惧鐘舵�佽〃鏍兼暟鎹�
+      equipmentStatusList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        equipmentNo: null,
+        equipmentName: null,
+        workshopCode: null,
+        productionLineCode: null,
+        processesCode: null,
+        eqStatus: null,
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        id: [
+          { required: true, message: "ID涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 鏌ヨ璁惧鐘舵�佸垪琛� */
+    getList() {
+      this.loading = true;
+      listEquipmentStatus(this.queryParams).then(response => {
+        this.equipmentStatusList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        id: null,
+        equipmentNo: null,
+        equipmentName: null,
+        workshopCode: null,
+        productionLineCode: null,
+        processesCode: null,
+        eqStatus: null,
+        spareField1: null,
+        spareField2: null,
+        remarks: null,
+        updateTime: null
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.titleName = "娣诲姞璁惧鐘舵��";
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getEquipmentStatus(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.titleName = "淇敼璁惧鐘舵��";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateEquipmentStatus(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addEquipmentStatus(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎璁惧鐘舵�佺紪鍙蜂负"' + ids + '"鐨勬暟鎹」锛�').then(function() {
+        return delEquipmentStatus(ids);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('em/equipmentStatus/export', {
+        ...this.queryParams
+      }, `equipmentStatus_${new Date().getTime()}.xlsx`)
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/main/kb/stationTerminal/index.vue b/jcdm-ui/src/views/main/kb/stationTerminal/index.vue
new file mode 100644
index 0000000..81c68e6
--- /dev/null
+++ b/jcdm-ui/src/views/main/kb/stationTerminal/index.vue
@@ -0,0 +1,445 @@
+<template>
+  <div class="app-container">
+   <el-row :gutter="5">
+     <el-col :span="6">
+       <el-card shadow="never">
+         <span class="head-font">宸ヤ綅缂栧彿 : {{headContent.processesCode}}</span>
+       </el-card>
+     </el-col>
+     <el-col :span="6">
+       <el-card shadow="never">
+         <span class="head-font">宸ヤ綅鍚嶇О : {{headContent.processesName}}</span>
+       </el-card>
+     </el-col>
+     <el-col :span="12">
+       <el-card shadow="never">
+         <span class="head-font">鎬绘垚缂栫爜 : {{headContent.sfcCode}}</span>
+         <el-input v-model="content" style="float: right;width: 150px;" placeholder="璇疯緭鍏ュ唴瀹�"></el-input>
+         <el-button @click="scanCompleted" style="float: right" type="primary">鎵爜瀹屾垚</el-button>
+         <el-button @click="clearClick" style="float: right" type="danger">娓呴櫎</el-button>
+       </el-card>
+     </el-col>
+
+   </el-row>
+   <el-row :gutter="5" style="margin-top: 5px">
+     <el-col :span="6" >
+       <el-card class="bottom-card">
+         <div slot="header" class="clearfix">
+           <i class="el-icon-tickets"></i>
+           <span style="font-weight: bold">褰撳墠宸ヤ欢淇℃伅</span>
+         </div>
+         <el-descriptions :column="1" :label-style="{'font-size': '15px'}" border :content-style="{'min-width': '150px'}">
+           <el-descriptions-item label="宸ュ崟缂栧彿">
+               <span>{{workpieceInformation.workOrderCode}}</span>
+           </el-descriptions-item>
+           <el-descriptions-item label="浜у搧缂栧彿">
+             <span>{{workpieceInformation.productCode}}</span>
+           </el-descriptions-item>
+           <el-descriptions-item label="浜у搧鍨嬪彿">
+             <span>{{workpieceInformation.productModel}}</span>
+           </el-descriptions-item>
+           <el-descriptions-item label="浜у搧鍚嶇О">
+             <span>{{workpieceInformation.productName}}</span>
+           </el-descriptions-item>
+           <el-descriptions-item label="鑺傛媿">
+             <span>{{workpieceInformation.beat}}</span>
+           </el-descriptions-item>
+         </el-descriptions>
+         <el-divider></el-divider>
+         <el-row>
+           <el-col :span="12">
+             <el-button class="circle-button" :class="cakeLamp.plcState ? 'circle-green-animate':'circle-red'" circle></el-button>
+             <span style="display: none">{{cakeLamp.plcState}}</span>
+             <span>&nbsp;PLC鐘舵��</span>
+           </el-col>
+           <el-col :span="12">
+             <el-button class="circle-button" :class="cakeLamp.scannerState ? 'circle-green-animate':'circle-red'" circle></el-button>
+             <span style="display: none">{{cakeLamp.scannerState}}</span>
+             <span>&nbsp;鎵爜鏋姸鎬�</span>
+           </el-col>
+         </el-row>
+         <el-row style="margin-top: 20px">
+           <el-col :span="12">
+             <el-button class="circle-button" :class="cakeLamp.InPlace ? 'circle-green':'circle-red'" circle></el-button>
+             <span style="display: none">{{cakeLamp.InPlace}}</span>
+             <span>&nbsp;宸ヤ欢鍒颁綅</span>
+           </el-col>
+           <el-col :span="12">
+             <el-button class="circle-button" :class="cakeLamp.scanFinish ? 'circle-green':'circle-red'" circle></el-button>
+             <span style="display: none">{{cakeLamp.scanFinish}}</span>
+             <span>&nbsp;鎵爜瀹屾垚</span>
+           </el-col>
+         </el-row>
+         <el-row style="margin-top: 20px">
+           <el-col :span="12">
+             <el-button class="circle-button" :class="cakeLamp.startWork ? 'circle-green':'circle-red'" circle></el-button>
+             <span style="display: none">{{cakeLamp.startWork}}</span>
+             <span>&nbsp;寮�濮嬩綔涓�</span>
+           </el-col>
+           <el-col :span="12">
+             <el-button class="circle-button" :class="cakeLamp.release ? 'circle-green':'circle-red'" circle></el-button>
+             <span style="display: none">{{cakeLamp.release}}</span>
+             <span>&nbsp;鍏佽鏀捐</span>
+           </el-col>
+
+         </el-row>
+         <el-row style="margin-top: 20px">
+           <el-col :span="12">
+             <el-input v-model="serialPortContent" style="width: 150px;" placeholder="璇疯緭鍏ュ唴瀹�"></el-input>
+
+           </el-col>
+           <el-col :span="12">
+             <el-button @click="serialPortMethod" type="primary">涓插彛鑾峰彇鏁版嵁</el-button>
+
+           </el-col>
+         </el-row>
+         <el-row style="margin-top: 20px">
+             <el-button @click="Release" type="primary">鏀捐</el-button>
+         </el-row>
+       </el-card>
+
+     </el-col>
+     <el-col :span="18">
+       <el-tabs type="border-card"  style="height: 600px" v-model="activeName" @tab-click="changeMenu">
+         <el-tab-pane name="first">
+           <span slot="label"> <a class="el-icon-date"></a>棣栭〉</span>
+           <el-col :span="8">
+             <el-table :cell-style="rowStyle" :data="formulaChildList">
+               <el-table-column label="鎺掑簭" width="60" align="center" prop="stepSort">
+               </el-table-column>
+               <el-table-column label="鎿嶄綔鍐呭" :show-overflow-tooltip='true' align="center" prop="operationSteps">
+               </el-table-column>
+             </el-table>
+           </el-col>
+           <el-col :span="16">
+             <el-image style="height: 520px;width: 100%" :src="imgSrc"></el-image>
+           </el-col>
+         </el-tab-pane>
+         <el-tab-pane name="second">
+           <span slot="label"> <b class="el-icon-date"></b>鐗╂枡BOM</span>
+           <el-empty>
+             <span slot="description">鏆傛棤鏁版嵁</span>
+           </el-empty>
+         </el-tab-pane>
+         <el-tab-pane name="third">
+           <span slot="label"> <b class="el-icon-date"></b>閲囬泦娓呭崟</span>
+           <el-empty>
+             <span slot="description">鏆傛棤鏁版嵁</span>
+           </el-empty>
+         </el-tab-pane>
+         <el-tab-pane name="fourth">
+           <span slot="label"> <b class="el-icon-date"></b>瀹夌伅鐘舵��</span>
+           <el-empty>
+             <span slot="description">鏆傛棤鏁版嵁</span>
+           </el-empty>
+         </el-tab-pane>
+         <el-tab-pane name="fifth">
+           <span slot="label"> <b class="el-icon-date"></b>宸ヨ壓閰嶆柟</span>
+           <el-empty>
+             <span slot="description">鏆傛棤鏁版嵁</span>
+           </el-empty>
+         </el-tab-pane>
+       </el-tabs>
+     </el-col>
+   </el-row>
+  </div>
+</template>
+<script>
+import {listWorkReport} from "@/api/main/om/workReport/workReport";
+import {listStationConf,getIpv4} from "@/api/main/sc/stationConf";
+import {listFormulaChild, releaseCheck, updateResults, workpieceRelease} from "@/api/main/bs/formulaChild/formulaChild";
+
+export default {
+  name: "stationTerminal",
+  data() {
+    return {
+      serialPortContent: '',
+      // 鏌ヨ鍙傛暟
+      formulaChildParams: {
+        pageNum: 1,
+        pageSize: 10,
+        productCode: null,
+        processesCode: null,
+      },
+      // 閰嶆柟閰嶇疆瀛愪俊鎭〃鏍兼暟鎹�
+      formulaChildList: [],
+      ipAddress: '',
+      imgSrc: '',
+      headContent: {
+        processesCode: 'OP1010',
+        processesName: '璐存爣鏈�-璐寸爜',
+        sfcCode: '1000000000000001',
+      },
+      workpieceInformation: {
+        workOrderCode: null,
+        productCode: null,
+        productModel: null,
+        productName: null,
+        beat: null,
+      },
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        sfcCode: null,
+      },
+      // 鏌ヨ鍙傛暟
+      StationConfQueryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        ipAddress: null,
+      },
+      cakeLamp: {
+        plcState: 1, //plc
+        scannerState: 1, //鎵爜鏋�
+        InPlace: 0, //宸ヤ欢鍒颁綅
+        scanFinish: 0,
+        startWork: 0,
+        release: 0 //鍏佽鏀捐
+      },
+      content: '',
+      activeName: 'first',
+      url: "ws://192.168.10.252:8080/websocket/message/",
+      message: "",
+      text_content: "",
+      ws: null,
+      inputValue: '9'
+    }
+  },
+  beforeDestroy() {
+    this.exit();
+  },
+  created() {
+    this.initStation();
+    // this.getStationConfList();
+    // setTimeout(() => {
+    //   this.connectWebsocket();
+    // }, 3000);
+  },
+  mounted() {
+
+  },
+  methods: {
+    Release(){
+      let formulaChildParams = {
+        productCode: this.workpieceInformation.productCode,
+        processesCode: this.headContent.processesCode
+      }
+      releaseCheck(formulaChildParams).then(response => {
+        if(response.data === 0){
+          //鏀瑰彉鐘舵��
+          workpieceRelease(formulaChildParams).then(response => {
+          });
+          this.$message('鏀捐鎴愬姛锛�');
+          this.formulaChildList = []
+          this.getListFormulaChild()
+        }else {
+          this.$message('姝ラ鏈畬鎴愪笉璁告斁琛岋紒');
+        }
+      });
+    },
+    serialPortMethod(){
+      let formulaChildParams = {
+        materialCode: this.serialPortContent
+      }
+      updateResults(formulaChildParams).then(response => {
+        this.getListFormulaChild()
+      });
+    },
+    rowStyle({ row }) {
+      if (row.results === 'OK') {
+        return 'background-color: PaleGreen';
+      } else if (row.results === 'NG') {
+        return 'background-color: LightSalmon';
+      }
+      return '';
+    },
+    /** 鏌ヨ閰嶆柟閰嶇疆瀛愪俊鎭垪琛� */
+    getListFormulaChild() {
+      this.formulaChildParams.productCode = this.workpieceInformation.productCode
+      this.formulaChildParams.processesCode = this.headContent.processesCode
+      listFormulaChild(this.formulaChildParams).then(response => {
+        this.formulaChildList = response.rows;
+      });
+    },
+    changeMenu(tab, event) {
+      console.log(tab, event);
+    },
+    clearClick(){
+      this.$message('杩欐槸涓�鏉℃竻闄ゆ秷鎭彁绀�');
+      this.headContent.sfcCode = null
+    },
+    scanCompleted(){
+      this.$message('鎵爜瀹屾垚'+this.content);
+      this.headContent.sfcCode = this.content
+      this.queryParams.sfcCode = this.content
+      this.getList()
+      this.getListFormulaChild()
+      this.cakeLamp.scanFinish = 1
+      this.cakeLamp.startWork = 1
+
+    },
+    /** 鏌ヨ鎶ュ伐璁板綍 琛ㄥ垪琛� */
+    async getList() {
+      await listWorkReport(this.queryParams).then(response => {
+        let rowsData = response.rows[0];
+        console.log(rowsData)
+        this.workpieceInformation.workOrderCode = rowsData.workOrderCode;
+        this.workpieceInformation.productCode = rowsData.productCode;
+        this.workpieceInformation.productModel = rowsData.productModel;
+        this.workpieceInformation.productName = rowsData.productName;
+        this.timer = setInterval(() => {
+          this.workpieceInformation.beat++;
+        }, 1000);
+      });
+      this.getListFormulaChild()
+
+    },
+    allowRelease(){
+      clearInterval(this.timer);
+      this.$message('淇濆瓨鑺傛媿涓�'+this.workpieceInformation.beat+'绉�');
+    },
+    /** 鏌ヨ宸ヤ綅缁堢閰嶇疆鍒楄〃 */
+    // async getStationConfList() {
+    //   await getIpv4().then(response => {
+    //     this.StationConfQueryParams.ipAddress = response.msg
+    //     console.log('鏌ヨ鍒版湰宸ヤ綅IP涓�'+this.StationConfQueryParams.ipAddress)
+    //   });
+    //   listStationConf(this.StationConfQueryParams).then(response => {
+    //     let rows = response.rows[0]
+    //     if(response.rows.length===0){
+    //       this.$message('璇ュ伐浣嶆病鏈夐厤缃甀P锛岃鑱旂郴绠$悊鍛橀厤缃甀P');
+    //       return
+    //     }
+    //     this.headContent.processesName = rows.processesName
+    //     this.headContent.processesCode = rows.processesCode
+    //     console.log('璁剧疆宸ヤ綅缂栫爜'+this.headContent.processesCode)
+    //
+    //   });
+    // },
+    // connectWebsocket() {
+    //   console.log('websocket杩炴帴宸ヤ綅涓�'+this.headContent.processesCode)
+    //   const wsuri = this.url + this.headContent.processesCode;
+    //   this.ws = new WebSocket(wsuri);
+    //   const self = this;
+    //   this.ws.onopen = function (event) {
+    //     // self.text_content = self.text_content + "宸茬粡鎵撳紑杩炴帴!" + "\n";
+    //     this.$message('websocket杩炴帴鎴愬姛锛�');
+    //   };
+    //   this.ws.onmessage = function (event) {
+    //     self.text_content = event.data + "\n";
+    //     console.log(event.data)
+    //     if(event.data === "IN"){
+    //       self.cakeLamp.InPlace = "1"
+    //     }else if(event.data === "OUT"){
+    //       self.cakeLamp.outRsSign = "1"
+    //     }
+    //   };
+    // },
+    exit() {
+      if (this.ws) {
+        this.ws.close();
+        this.ws = null;
+      }
+    },
+    send() {
+      if (this.ws) {
+        this.ws.send(this.message);
+      } else {
+        alert("鏈繛鎺ュ埌鏈嶅姟鍣�");
+      }
+    },
+    async initStation(){
+      await getIpv4().then(response => {
+        this.StationConfQueryParams.ipAddress = response.msg
+        console.log('鏌ヨ鍒版湰宸ヤ綅IP涓�'+this.StationConfQueryParams.ipAddress)
+      });
+      await listStationConf(this.StationConfQueryParams).then(response => {
+        let rows = response.rows[0]
+        if(response.rows.length===0){
+          this.$message('璇ュ伐浣嶆病鏈夐厤缃甀P锛岃鑱旂郴绠$悊鍛橀厤缃甀P');
+          return
+        }
+        this.headContent.processesName = rows.processesName
+        this.headContent.processesCode = rows.processesCode
+        console.log('璁剧疆宸ヤ綅缂栫爜'+this.headContent.processesCode)
+
+      });
+      console.log('websocket杩炴帴宸ヤ綅涓�'+this.headContent.processesCode)
+      const wsuri = this.url + this.headContent.processesCode;
+      this.ws = new WebSocket(wsuri);
+      const self = this;
+      this.ws.onopen = function (event) {
+        this.$message('websocket杩炴帴鎴愬姛锛�');
+      };
+      this.ws.onmessage = function (event) {
+        self.text_content = event.data + "\n";
+        console.log(event.data)
+        if(event.data === "IN"){
+          self.cakeLamp.InPlace = 1
+        }else if(event.data === "OUT"){
+          self.cakeLamp.release = 1
+          setTimeout(() => {
+            this.resetting()
+          }, 2000); // 寤舵椂2绉掕Е鍙�
+        }else if(event.data === 'TIGHTEN'){
+          console.log('寮�濮嬫嫥绱�')
+          this.formulaChildList = []
+          self.getListFormulaChild()
+        }
+      };
+    },
+    resetting() {
+      this.cakeLamp = {
+        InPlace: 0,
+        release: 0,
+        startWork: 0,
+        scanFinish: 0,
+      }
+    }
+  }
+}
+
+</script>
+<style scoped>
+.bottom-card{
+  height: 600px;
+}
+.circle-button{
+  height: 30px;
+  width: 30px;
+}
+.circle-red {
+  background-color: #e01a4f;
+}
+.circle-green {
+  background-color: green;
+}
+.circle-green-animate {
+  background-color: green;
+  animation: circle-green-animate 2s infinite;
+}
+  @keyframes circle-green-animate {
+    50% {
+      opacity: 0.6;
+    }
+    0% {
+      opacity: 0.2;
+    }
+  }
+.head-font{
+  font-weight: bold;
+  font-size: 25px;
+}
+span{
+  font-size: 15px;
+}
+.el-table .warning-row {
+  background: oldlace;
+}
+
+.el-table .success-row {
+  background: #f0f9eb;
+}
+</style>
+
diff --git a/jcdm-ui/src/views/main/om/productionOrde/index.vue b/jcdm-ui/src/views/main/om/productionOrde/index.vue
new file mode 100644
index 0000000..5c5df66
--- /dev/null
+++ b/jcdm-ui/src/views/main/om/productionOrde/index.vue
@@ -0,0 +1,656 @@
+<template>
+  <div class="app-container">
+    <el-card class="box-card">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label-width="80" label="鐢熶骇宸ュ崟鍙�" prop="workOrderNo">
+        <el-input
+          v-model="queryParams.workOrderNo"
+          placeholder="璇疯緭鍏ョ敓浜у伐鍗曞彿"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="浜у搧鍚嶇О" prop="productName">
+        <el-input
+          v-model="queryParams.productName"
+          placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="宸ュ崟鐘舵��" prop="orderStatus">
+        <el-select v-model="queryParams.orderStatus" placeholder="璇烽�夋嫨宸ュ崟鐘舵��" clearable>
+          <el-option
+            v-for="dict in dict.type.order_state"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item style="float: right">
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button type="warning" icon="el-icon-copy-document" size="mini" @click="advancedQuery">楂樼骇鏌ヨ</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+    <el-form :model="queryParams" ref="queryParams" size="small" :inline="true" v-show="advancedShowSearch" label-width="68px">
+      <el-form-item style="margin-left: 14px" label="浜у搧缂栧彿" prop="productCode">
+        <el-input
+          v-model="queryParams.productCode"
+          placeholder="璇疯緭鍏ヤ骇鍝佺紪鍙�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="璁㈠崟缂栧彿" prop="salesOrderCode">
+        <el-input
+          v-model="queryParams.salesOrderCode"
+          placeholder="璇疯緭鍏ヨ鍗曠紪鍙�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="杞﹂棿缂栧彿" prop="workshopCode">
+        <el-input
+          v-model="queryParams.workshopCode"
+          placeholder="璇疯緭鍏ヨ溅闂寸紪鍙�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="浜х嚎缂栧彿" prop="lineCode">
+        <el-input
+          v-model="queryParams.lineCode"
+          placeholder="璇疯緭鍏ヤ骇绾跨紪鍙�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item style="margin-left: 7px" label-width="80" label="浜у搧BOM" prop="bomCode">
+        <el-input
+          v-model="queryParams.bomCode"
+          placeholder="璇疯緭鍏ヤ骇鍝丅OM"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="宸ヨ壓娴佺▼" prop="routeCode">
+        <el-input
+          v-model="queryParams.routeCode"
+          placeholder="璇疯緭鍏ュ伐鑹烘祦绋�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+
+      <el-form-item label="宸ヨ壓閰嶆柟" prop="recipeCode">
+        <el-input
+          v-model="queryParams.recipeCode"
+          placeholder="璇疯緭鍏ュ伐鑹洪厤鏂�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+    </el-form>
+    </el-card>
+
+    <el-card style="margin-top: 10px" class="box-card">
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['om:productionOrde:add']"
+        >鏂板</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['om:productionOrde:edit']"
+        >淇敼</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['om:productionOrde:remove']"
+        >鍒犻櫎</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['om:productionOrde:export']"
+        >瀵煎嚭</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-upload2"
+          :disabled="move"
+          size="mini"
+          @click="moveUp(val => val, 'up')"
+        >涓婄Щ</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          :disabled="move"
+          @click="moveUp(val => val, 'down')"
+        >涓嬬Щ</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+      <el-table border v-loading="loading" :data="productionOrdeList" @selection-change="handleSelectionChange">
+        <el-table-column type="selection" width="55" align="center" />
+        <el-table-column label="鐢熶骇宸ュ崟鍙�" width="160" align="center">
+          <template slot-scope="scope">
+            <router-link :to="{path: '/main/workReport-data/index/', query: {workOrderNo: scope.row.workOrderNo} }" class="link-type">
+              <span>{{ scope.row.workOrderNo }}</span>
+            </router-link>
+          </template>
+        </el-table-column>
+        <el-table-column label="璁㈠崟缂栧彿" width="140" align="center" prop="salesOrderCode">
+        </el-table-column>
+        <el-table-column label="浜у搧缂栧彿" width="140" align="center" prop="productCode">
+        </el-table-column>
+        <el-table-column label="浜у搧鍚嶇О" width="160" align="center" prop="productName">
+        </el-table-column>
+        <el-table-column label="宸ュ崟鐘舵��" align="center" prop="orderStatus">
+          <template slot-scope="scope">
+            <dict-tag :options="dict.type.order_state" :value="scope.row.orderStatus"/>
+          </template>
+        </el-table-column>
+        <el-table-column label="杞﹂棿缂栧彿" align="center" prop="workshopCode">
+        </el-table-column>
+        <el-table-column label="浜х嚎缂栧彿" align="center" prop="lineCode">
+        </el-table-column>
+        <el-table-column label="宸ヨ壓娴佺▼" width="140" align="center" prop="routeCode">
+        </el-table-column>
+        <el-table-column label="浜у搧BOM" width="140" align="center" prop="bomCode">
+        </el-table-column>
+        <el-table-column label="宸ヨ壓閰嶆柟" width="140" align="center" prop="recipeCode">
+        </el-table-column>
+        <el-table-column label="璁″垝鏁伴噺" align="center" prop="planQty">
+        </el-table-column>
+        <el-table-column label="瀹為檯鏁伴噺" align="center" prop="actualQty">
+        </el-table-column>
+        <el-table-column label="瀹為檯涓婄嚎鏁伴噺" width="100" align="center" prop="actualOnlineQty">
+        </el-table-column>
+        <el-table-column label="闇�姹傛棩鏈�" align="center" prop="demandDate" width="180">
+        </el-table-column>
+        <el-table-column label="璁″垝寮�濮嬫椂闂�" width="160" align="center" prop="planStartTime">
+        </el-table-column>
+        <el-table-column label="璁″垝缁撴潫鏃堕棿" width="160" align="center" prop="planEndTime">
+        </el-table-column>
+        <el-table-column label="瀹為檯寮�濮嬫椂闂�" width="160" align="center" prop="actualStartTime">
+        </el-table-column>
+        <el-table-column label="瀹為檯缁撴潫鏃堕棿" width="160" align="center" prop="actualEndTime">
+        </el-table-column>
+        <el-table-column width="160" label="鍒涘缓鏃堕棿" align="center" prop="createTime">
+        </el-table-column>
+        <el-table-column width="160" label="鏇存柊鏃堕棿" align="center" prop="updateTime">
+        </el-table-column>
+        <el-table-column label="鍒涘缓浜�" width="80" align="center" prop="createUser">
+        </el-table-column>
+        <el-table-column label="淇敼浜�" width="80" align="center" prop="updateUser">
+        </el-table-column>
+        <el-table-column label="澶囨敞" width="100" align="center" prop="remarks">
+        </el-table-column>
+        <el-table-column label="娴佹按鍙�" align="center" prop="streamNumber">
+        </el-table-column>
+        <el-table-column label="瀹㈡埛" width="80" align="center" prop="custom">
+        </el-table-column>
+        <el-table-column fixed="right" width="350" label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+          <template slot-scope="scope">
+            <!--  宸ュ崟鐘舵�侊紙1鍒涘缓銆�2宸插彂甯冦��3鐢熶骇涓��4宸插喕缁撱��5宸插畬宸ャ��6宸插叧闂級 -->
+            <el-button type="success" :disabled="scope.row.orderStatus !== '1'"  style="width: 72px" plain @click="handleCommand('3',scope.row.id)" size="mini">寮�濮�</el-button>
+            <el-button style="width: 72px" :disabled="scope.row.orderStatus !== '2' && scope.row.orderStatus !== '3'" v-if="scope.row.orderStatus !== '2'&&  scope.row.orderStatus !== '4'" plain @click="handleCommand('4',scope.row.id)" type="warning" size="mini">鍐荤粨</el-button>
+            <el-button style="width: 72px" :disabled="scope.row.orderStatus !== '4'" v-if="scope.row.orderStatus === '4'" plain @click="handleCommand('3',scope.row.id)" type="warning" size="mini">瑙e喕</el-button>
+            <el-button style="width: 72px" :disabled="scope.row.orderStatus !== '1'" plain @click="handleCommand('6',scope.row.id)" v-if="scope.row.orderStatus === '1'||scope.row.orderStatus === '3'||scope.row.orderStatus === '4'||scope.row.orderStatus === '5'" type="danger" size="mini">鍏抽棴</el-button>
+            <el-button style="width: 72px" :disabled="scope.row.orderStatus !== '6'" plain @click="handleCommand('1',scope.row.id)" v-if="scope.row.orderStatus === '6' " type="success" size="mini">鍚敤</el-button>
+<!--            <el-button-->
+<!--              :disabled="scope.row.orderStatus !== '1'"-->
+<!--              size="mini"-->
+<!--              type="success"-->
+<!--              style="width: 72px"-->
+<!--              icon="el-icon-edit"-->
+<!--              @click="handleUpdate(scope.row)"-->
+<!--              v-hasPermi="['om:productionOrde:edit']"-->
+<!--            >淇敼</el-button>-->
+<!--            <el-button-->
+<!--              :disabled="scope.row.orderStatus !== '1'"-->
+<!--              size="mini"-->
+<!--              type="warning"-->
+<!--              style="width: 72px"-->
+<!--              icon="el-icon-delete"-->
+<!--              @click="handleDelete(scope.row)"-->
+<!--              v-hasPermi="['om:productionOrde:remove']"-->
+<!--            >鍒犻櫎</el-button>-->
+            <el-button style="width: 72px" :disabled="scope.row.orderStatus === '4'||scope.row.orderStatus === '6'" v-if="scope.row.orderStatus !== '5'" @click="handleCommand('5',scope.row.id)" type="success" size="mini">瀹屾垚</el-button>
+            <el-button style="width: 72px" :disabled="scope.row.orderStatus === '5'" v-if="scope.row.orderStatus === '5'" type="success" size="mini">宸插畬宸�</el-button>            <el-button style="width: 72px" :disabled="scope.row.orderStatus !== '6'" plain @click="handleCommand('1',scope.row.id)" v-if="scope.row.orderStatus === '6' " type="success" size="mini">鍚敤</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+    </el-card>
+
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 娣诲姞鎴栦慨鏀圭敓浜у伐鍗曞璇濇 -->
+    <el-dialog v-dialogpop-up :title="title" :visible.sync="open" width="1000px" append-to-body>
+       <span slot="title">
+        <i class="el-icon-s-order"></i>
+        {{titleName}}
+      </span>
+      <el-form ref="form" inline :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="宸ュ崟鍙�" prop="workOrderNo">
+          <el-input v-model="form.workOrderNo" placeholder="璇疯緭鍏ョ敓浜у伐鍗曞彿" />
+        </el-form-item>
+        <el-form-item label="璁㈠崟缂栧彿" prop="salesOrderCode">
+          <el-input v-model="form.salesOrderCode" placeholder="璇疯緭鍏ヨ鍗曠紪鍙�" />
+        </el-form-item>
+        <el-form-item label="浜у搧缂栧彿" prop="productCode">
+          <el-input v-model="form.productCode" placeholder="璇烽�夋嫨浜у搧" >
+            <el-button slot="append" @click="handleSelectProduct" icon="el-icon-search"></el-button>
+          </el-input>
+          <ItemSelect ref="itemSelect" @onSelected="onItemSelected" > </ItemSelect>
+        </el-form-item>
+        <el-form-item label="浜у搧鍚嶇О" prop="productName">
+          <el-input v-model="form.productName" disabled placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�" />
+        </el-form-item>
+        <el-form-item label="杞﹂棿缂栧彿" prop="workshopCode">
+          <el-select style="width: 93%" @change="handleSelectChange(form.workshopCode)" v-model="form.workshopCode" placeholder="璇烽�夋嫨杞﹂棿缂栧彿">
+            <el-option
+              v-for="item in options"
+              :key="item.workshopCode"
+              :label="item.workshopName"
+              :value="item.workshopCode">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item style="margin-left: -15px" label="浜х嚎缂栧彿" prop="lineCode">
+          <el-select style="width: 93%" v-model="form.lineCode" placeholder="璇烽�夋嫨浜х嚎缂栧彿">
+            <el-option
+              v-for="item in lineOptions"
+              :key="item.lineCode"
+              :label="item.lineName"
+              :value="item.lineCode">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="宸ヨ壓娴佺▼" prop="routeCode">
+          <el-input v-model="form.routeCode" disabled placeholder="璇疯緭鍏ュ伐鑹烘祦绋�" />
+        </el-form-item>
+        <el-form-item label="浜у搧BOM" prop="bomCode">
+          <el-input v-model="form.bomCode" disabled placeholder="璇疯緭鍏ヤ骇鍝丅OM" />
+        </el-form-item>
+        <el-form-item label="宸ヨ壓閰嶆柟" prop="recipeCode">
+          <el-input v-model="form.recipeCode" placeholder="璇疯緭鍏ュ伐鑹洪厤鏂�" />
+        </el-form-item>
+        <el-form-item label="璁″垝鏁伴噺" prop="planQty">
+          <el-input v-model="form.planQty" placeholder="璇疯緭鍏ヨ鍒掓暟閲�" />
+        </el-form-item>
+        <el-form-item label="闇�姹傛棩鏈�" prop="demandDate">
+          <el-date-picker style="width: 88%" clearable
+            v-model="form.demandDate"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="璇烽�夋嫨闇�姹傛棩鏈�">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item style="margin-left: -30px" label="澶囨敞" prop="remarks">
+          <el-input v-model="form.remarks" placeholder="璇疯緭鍏ュ娉�" />
+        </el-form-item>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item style="margin-left: 10px" label-width="120" label="璁″垝寮�濮嬫椂闂�" prop="planStartTime">
+              <el-date-picker clearable
+                v-model="form.planStartTime"
+                type="date"
+                value-format="yyyy-MM-dd"
+                placeholder="璇烽�夋嫨璁″垝寮�濮嬫椂闂�">
+              </el-date-picker>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item style="margin-left: 76px" label-width="120" label="璁″垝缁撴潫鏃堕棿" prop="planEndTime">
+              <el-date-picker clearable
+                v-model="form.planEndTime"
+                type="date"
+                value-format="yyyy-MM-dd"
+                placeholder="璇烽�夋嫨璁″垝缁撴潫鏃堕棿">
+              </el-date-picker>
+            </el-form-item>
+          </el-col>
+
+        </el-row>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+
+  </div>
+</template>
+
+<script>
+import { listLineInfo } from "@/api/main/bs/lineInfo/lineInfo";
+import { listWorkshop } from "@/api/main/bs/workshop/workshop";
+import { listProductBom } from "@/api/main/bs/ProductBom/ProductBom";
+import { listTechnologyRoute} from "@/api/main/bs/technologyRoute/technologyRoute";
+import ItemSelect  from "@/components/itemSelect/single.vue";
+import { upDownMove, listProductionOrde, getProductionOrde, delProductionOrde, addProductionOrde, updateProductionOrde } from "@/api/main/om/productionOrde/productionOrde";
+
+export default {
+  name: "ProductionOrde",
+  dicts: ['order_state'],
+  components: {
+    ItemSelect ,
+  },
+  data() {
+    return {
+      titleName: '',
+      options: [],
+      lineOptions: [],
+      showFlag:false,
+      advancedShowSearch: false,
+      workOrder: {
+        status: 'ss'
+      },
+      // 閬僵灞�
+      loading: true,
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      move: true,
+      selectedRowIndex: -1, // 瀛樺偍閫変腑琛岀殑绱㈠紩
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 鐢熶骇宸ュ崟琛ㄦ牸鏁版嵁
+      productionOrdeList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        workOrderNo: null,
+        salesOrderCode: null,
+        productCode: null,
+        productName: null,
+        workshopCode: null,
+        lineCode: null,
+        routeCode: null,
+        bomCode: null,
+        recipeCode: null,
+        orderStatus: null,
+        custom: null,
+        marketAreaCode: null,
+        softwareVersionCode: null,
+        productCompanyCode: null,
+        frontEndId: 0,
+        idNums: null,
+        flag: null,
+
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      updateStatusParameter: {
+        id: null,
+        orderStatus: null
+      },
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        id: [
+          { required: true, message: "ID涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+      }
+    };
+  },
+  created() {
+    this.getList();
+    this.initWorkshop();
+  },
+  methods: {
+    moveUp(row, val){
+      console.log(val)
+      const ids = row.id || this.ids
+      let str = JSON.stringify(ids);
+      let num = BigInt(str.replace(/[\[\]]/g, ''));
+      this.queryParams.frontEndId = num
+      this.queryParams.idNums = ids
+      this.queryParams.flag = val
+      upDownMove(this.queryParams).then(response => {
+        this.$modal.msgSuccess("绉诲姩鎴愬姛");
+        this.getList();
+      });
+    },
+    initWorkshop(){
+      listWorkshop(this.queryParams).then(response => {
+        this.options = response.rows;
+      });
+    },
+    // 鍦ㄨ繖閲岀紪鍐欏鐞嗛�変腑浜嬩欢鐨勯�昏緫
+    handleSelectChange(selectedOption) {
+      this.form.lineCode = null;
+      let params = {
+        workshopCode: selectedOption
+      };
+      listLineInfo(params).then(response => {
+        this.lineOptions = response.rows;
+      });
+    },
+    //鐗╂枡閫夋嫨寮瑰嚭妗�
+    onItemSelected(obj){
+      if(obj !== undefined && obj !== null){
+        let productCode = obj.materialCode;
+        this.form.productCode = productCode;
+        this.form.productName = obj.materialName;
+        this.queryParams.productCode = productCode
+        listTechnologyRoute(this.queryParams).then(response => {
+          this.form.routeCode = response.rows[0].routeCode;
+        });
+        listProductBom(this.queryParams).then(response => {
+          this.form.bomCode = response.rows[0].bomCode;
+        });
+      }
+    },
+    handleSelectProduct(){
+      this.$refs.itemSelect.showFlag = true;
+    },
+    advancedQuery(){
+      this.advancedShowSearch = (this.advancedShowSearch) ? this.advancedShowSearch = false : this.advancedShowSearch = true;
+    },
+    handleCommand(status,id) {
+      console.log(status)
+      this.updateStatusParameter.id = id;
+      this.updateStatusParameter.orderStatus = status;
+      updateProductionOrde(this.updateStatusParameter).then(response => {
+        this.$modal.msgSuccess("淇敼鎴愬姛");
+        this.open = false;
+        this.getList();
+      });
+    },
+    /** 鏌ヨ鐢熶骇宸ュ崟鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listProductionOrde(this.queryParams).then(response => {
+        this.productionOrdeList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        id: null,
+        workOrderNo: null,
+        salesOrderCode: null,
+        productCode: null,
+        productName: null,
+        workshopCode: null,
+        lineCode: null,
+        routeCode: null,
+        bomCode: null,
+        recipeCode: null,
+        planQty: null,
+        actualQty: null,
+        badQty: null,
+        scrapQty: null,
+        repairQty: null,
+        actualOnlineQty: null,
+        onlineCompletionMark: null,
+        demandDate: null,
+        planStartTime: null,
+        planEndTime: null,
+        actualStartTime: null,
+        actualEndTime: null,
+        serialNumber: null,
+        orderStatus: null,
+        createTime: null,
+        updateTime: null,
+        createUser: null,
+        updateUser: null,
+        remarks: null,
+        streamNumber: null,
+        custom: null,
+        marketAreaCode: null,
+        softwareVersionCode: null,
+        productCompanyCode: null,
+        spareField1: null,
+        spareField2: null,
+        spareField3: null,
+        spareField4: null
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.move = selection.length!==1
+      if(!selection.length){
+        this.single = true
+        this.multiple = true
+      }else {
+        if(selection[0].orderStatus === '1' && selection.length === 1){
+          this.single = false
+          this.multiple = false
+        }
+      }
+
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.initWorkshop();
+      this.reset();
+      this.open = true;
+      this.titleName = "娣诲姞鐢熶骇宸ュ崟";
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.initWorkshop();
+      this.reset();
+      const id = row.id || this.ids
+      getProductionOrde(id).then(response => {
+        console.log(response.data)
+        this.form = response.data;
+        this.open = true;
+        this.titleName = "淇敼鐢熶骇宸ュ崟";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateProductionOrde(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addProductionOrde(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎鐢熶骇宸ュ崟缂栧彿涓�"' + ids + '"鐨勬暟鎹」锛�').then(function() {
+        return delProductionOrde(ids);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('om/productionOrde/export', {
+        ...this.queryParams
+      }, `productionOrde_${new Date().getTime()}.xlsx`)
+    }
+  }
+};
+</script>
+<style lang="scss" scoped>
+//::v-deep .el-dialog__header{
+//  /*background-color: #f8f8f8;*/
+//  background-color: #f8f8f9;
+//}
+</style>
diff --git a/jcdm-ui/src/views/main/om/workReport/index.vue b/jcdm-ui/src/views/main/om/workReport/index.vue
new file mode 100644
index 0000000..3b8652a
--- /dev/null
+++ b/jcdm-ui/src/views/main/om/workReport/index.vue
@@ -0,0 +1,378 @@
+<template>
+  <div class="app-container">
+    <el-card class ="box-card">
+      <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+        <el-form-item label="宸ュ崟缂栧彿" prop="workOrderCode">
+          <el-input
+            v-model="queryParams.workOrderCode"
+            placeholder="璇疯緭鍏ュ伐鍗曠紪鍙�"
+            clearable
+            @keyup.enter.native="handleQuery"
+          />
+        </el-form-item>
+        <el-form-item label="SFC鎬绘垚搴忓垪鍙�" prop="sfcCode" label-width="110px">
+          <el-input
+            v-model="queryParams.sfcCode"
+            placeholder="璇疯緭鍏FC鎬绘垚搴忓垪鍙�"
+            clearable
+            @keyup.enter.native="handleQuery"
+          />
+        </el-form-item>
+        <el-form-item style="float: right">
+          <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+          <el-button type="warning" icon="el-icon-copy-document" size="mini" @click="advancedQuery">楂樼骇鏌ヨ</el-button>
+          <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+        </el-form-item>
+        <el-form :model="queryParams" ref="queryParams" size="small" :inline="true" v-show="advancedShowSearch" label-width="68px">
+          <el-form-item label="浜у搧缂栧彿" prop="productCode">
+            <el-input
+              v-model="queryParams.productCode"
+              placeholder="璇疯緭鍏ヤ骇鍝佺紪鍙�"
+              clearable
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item label="浜у搧鍚嶇О" prop="productName">
+            <el-input
+              v-model="queryParams.productName"
+              placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�"
+              clearable
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item label="鏄惁鍚堟牸" prop="status">
+            <el-input
+              v-model="queryParams.status"
+              placeholder="璇疯緭鍏ユ槸鍚﹀悎鏍�"
+              clearable
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+        </el-form>
+      </el-form>
+    </el-card>
+
+    <el-card style="margin-top: 10px" class="box-card">
+        <el-row :gutter="10" class="mb8">
+          <el-col :span="1.5">
+            <el-button
+              type="primary"
+              plain
+              icon="el-icon-plus"
+              size="mini"
+              @click="handleAdd"
+              v-hasPermi="['om:workReport:add']"
+            >鏂板</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="success"
+              plain
+              icon="el-icon-edit"
+              size="mini"
+              :disabled="single"
+              @click="handleUpdate"
+              v-hasPermi="['om:workReport:edit']"
+            >淇敼</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="danger"
+              plain
+              icon="el-icon-delete"
+              size="mini"
+              :disabled="multiple"
+              @click="handleDelete"
+              v-hasPermi="['om:workReport:remove']"
+            >鍒犻櫎</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="warning"
+              plain
+              icon="el-icon-download"
+              size="mini"
+              @click="handleExport"
+              v-hasPermi="['om:workReport:export']"
+            >瀵煎嚭</el-button>
+          </el-col>
+          <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+        </el-row>
+        <el-table border v-loading="loading" :data="workReportList" @selection-change="handleSelectionChange">
+          <el-table-column type="selection" width="55" align="center" />
+          <el-table-column label="宸ュ崟缂栧彿" width="130" align="center" prop="workOrderCode"/>
+          <el-table-column label="SFC鎬绘垚搴忓垪鍙�" align="center" prop="sfcCode" />
+          <el-table-column label="浜у搧缂栧彿" align="center" prop="productCode" />
+          <el-table-column label="浜у搧鍚嶇О" align="center" prop="productName" />
+          <el-table-column label="涓婄嚎鏃堕棿" align="center" prop="upTime" />
+          <el-table-column label="涓嬬嚎鏃堕棿" align="center" prop="offlineTime" />
+          <el-table-column label="鏄惁鍚堟牸" align="center" prop="status">
+            <template slot-scope="scope">
+              <dict-tag :options="dict.type.sys_yes_no" :value="scope.row.status"/>
+            </template>
+          </el-table-column>
+          <el-table-column label="澶囨敞" align="center" prop="remark" />
+          <el-table-column fixed="right" width="200" label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+            <template slot-scope="scope">
+              <el-button
+                size="mini"
+                type="success"
+                plain
+                style="width: 72px"
+                icon="el-icon-edit"
+                @click="handleUpdate(scope.row)"
+                v-hasPermi="['om:workReport:edit']"
+              >淇敼</el-button>
+              <el-button
+                size="mini"
+                type="danger"
+                plain
+                style="width: 72px"
+                icon="el-icon-delete"
+                @click="handleDelete(scope.row)"
+                v-hasPermi="['om:workReport:remove']"
+              >鍒犻櫎</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+    </el-card>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 娣诲姞鎴栦慨鏀规姤宸ヨ褰曡〃瀵硅瘽妗� -->
+    <el-dialog v-dialogpop-up :title="title" :visible.sync="open" width="500px" append-to-body>
+      <span slot="title">
+        <i class="el-icon-s-order"></i>
+        {{titleName}}
+      </span>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="宸ュ崟缂栧彿" prop="workOrderCode">
+          <el-input v-model="form.workOrderCode" placeholder="璇疯緭鍏ュ伐鍗曠紪鍙�" />
+        </el-form-item>
+        <el-form-item label="SFC鎬绘垚搴忓垪鍙�" prop="sfcCode">
+          <el-input v-model="form.sfcCode" placeholder="璇疯緭鍏FC鎬绘垚搴忓垪鍙�" />
+        </el-form-item>
+        <el-form-item label="浜у搧缂栧彿" prop="productCode">
+          <el-input v-model="form.productCode" placeholder="璇疯緭鍏ヤ骇鍝佺紪鍙�" />
+        </el-form-item>
+        <el-form-item label="浜у搧鍚嶇О" prop="productName">
+          <el-input v-model="form.productName" placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�" />
+        </el-form-item>
+        <!--        <el-form-item label="鏄惁鍚堟牸" prop="status">-->
+        <!--          <el-input v-model="form.status" placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�" />-->
+        <!--        </el-form-item>-->
+        <el-form-item label="鏄惁鍚堟牸" prop="status">
+          <el-radio-group v-model="form.status">
+            <el-radio
+              v-for="dict in dict.type.sys_yes_no"
+              :key="dict.value"
+              :label="dict.value"
+            >{{dict.label}}</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="澶囨敞" prop="remark">
+          <el-input v-model="form.remark" placeholder="璇疯緭鍏ュ娉�" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listWorkReport, getWorkReport, delWorkReport, addWorkReport, updateWorkReport } from "@/api/main/om/workReport/workReport";
+
+export default {
+  name: "WorkReport",
+  dicts: ['sys_yes_no'],
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      titleName: "test",
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 鎶ュ伐璁板綍 琛ㄨ〃鏍兼暟鎹�
+      workReportList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      advancedShowSearch: false,
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        workOrderCode: null,
+        sfcCode: null,
+        productCode: null,
+        productName: null,
+        upTime: null,
+        offlineTime: null,
+        status: null,
+        createUser: null,
+        updateUser: null,
+        spareField1: null,
+        spareField2: null,
+        spareField3: null,
+        spareField4: null
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        id: [
+          { required: true, message: "涓婚敭id涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        workOrderCode: [
+          { required: true, message: "璇疯緭鍏ュ伐鍗曠紪鍙�", trigger: "blur" }
+        ],
+        sfcCode: [
+          { required: true, message: "璇疯緭鍏FC鎬绘垚搴忓垪鍙�", trigger: "blur" }
+        ],
+        productCode: [
+          { required: true, message: "璇疯緭鍏ヤ骇鍝佺紪鍙�", trigger: "blur" }
+        ],
+        productName: [
+          { required: true, message: "璇疯緭鍏ヤ骇鍝佸悕绉�", trigger: "blur" }
+        ],
+      }
+    };
+  },
+  created() {
+    let workOrderNo = this.$route.query.workOrderNo;
+    this.queryParams.workOrderCode = workOrderNo
+    this.queryRouteCode = workOrderNo
+    this.getList();
+    this.headerInformation();
+    this.getProcesses();
+  },
+  methods: {
+    advancedQuery(){
+      this.advancedShowSearch = (this.advancedShowSearch) ? this.advancedShowSearch = false : this.advancedShowSearch = true;
+    },
+    /** 鏌ヨ鎶ュ伐璁板綍 琛ㄥ垪琛� */
+    getList() {
+      this.loading = true;
+      listWorkReport(this.queryParams).then(response => {
+        this.workReportList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        id: null,
+        workOrderCode: null,
+        sfcCode: null,
+        productCode: null,
+        productName: null,
+        upTime: null,
+        offlineTime: null,
+        status: "Y",
+        createUser: null,
+        createTime: null,
+        updateUser: null,
+        updateTime: null,
+        remark: null,
+        spareField1: null,
+        spareField2: null,
+        spareField3: null,
+        spareField4: null
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.titleName = "娣诲姞鎶ュ伐璁板綍琛�";
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getWorkReport(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.titleName = "淇敼鎶ュ伐璁板綍琛�";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateWorkReport(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addWorkReport(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎鎶ュ伐璁板綍琛ㄧ紪鍙蜂负"' + ids + '"鐨勬暟鎹」锛�').then(function() {
+        return delWorkReport(ids);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('om/workReport/export', {
+        ...this.queryParams
+      }, `workReport_${new Date().getTime()}.xlsx`)
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/main/rm/repairData/index.vue b/jcdm-ui/src/views/main/rm/repairData/index.vue
new file mode 100644
index 0000000..dbaa47a
--- /dev/null
+++ b/jcdm-ui/src/views/main/rm/repairData/index.vue
@@ -0,0 +1,398 @@
+<template>
+  <div class="app-container">
+    <el-card class ="box-card">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="杩斾慨鏍囪瘑" prop="repairIdentification">
+        <el-input
+          v-model="queryParams.repairIdentification"
+          placeholder="璇疯緭鍏ヨ繑淇爣璇�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="绠变綋缂栫爜" prop="boxCode">
+        <el-input
+          v-model="queryParams.boxCode"
+          placeholder="璇疯緭鍏ョ浣撶紪鐮�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item style="float: right">
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+      </el-card>
+    <el-card style="margin-top: 10px"  height="250" class="box-card">
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['rm:repairData:add']"
+        >鏂板</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['rm:repairData:edit']"
+        >淇敼</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['rm:repairData:remove']"
+        >鍒犻櫎</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['rm:repairData:export']"
+        >瀵煎嚭</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading"  border :data="repairRecordList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="杩斾慨鏍囪瘑" align="center" prop="repairIdentification" />
+      <el-table-column label="绠变綋缂栫爜" align="center" prop="boxCode" />
+      <el-table-column label="宸ュ簭缂栫爜" align="center" prop="processesCode" />
+      <el-table-column label="鍘熺粨鏋�" align="center" prop="originalResult" />
+      <el-table-column label="杩斾慨缁撴灉" align="center" prop="repairResults" />
+      <el-table-column label="鍒涘缓鐢ㄦ埛" align="center" prop="createUser" />
+      <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['rm:repairData:edit']"
+          >淇敼</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['rm:repairData:remove']"
+          >鍒犻櫎</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+      <pagination
+        v-show="total>0"
+        :total="total"
+        :page.sync="queryParams.pageNum"
+        :limit.sync="queryParams.pageSize"
+        @pagination="getRepairRecordList"
+      />
+    </el-card>
+    <el-card style="margin-top: 10px" class="box-card">
+      <el-tabs type="border-card" >
+        <el-tab-pane>
+          <span slot="label"> <a class="el-icon-date"></a>鎷х揣鏁版嵁</span>
+          <template>
+            <el-table v-loading="loading" border :data="repairDataList" @selection-change="handleSelectionChange">
+              <el-table-column type="selection" width="55" align="center" />
+              <el-table-column label="绠变綋缂栫爜" align="center" prop="boxCode">
+              </el-table-column>
+              <el-table-column label="宸ヤ綅" align="center" prop="station">
+              </el-table-column>
+              <el-table-column label="鎷х揣娆℃暟" align="center" prop="tightenFrequency">
+              </el-table-column>
+              <el-table-column label="鎷х揣棰楁暟" align="center" prop="tightenPiecesNumber">
+              </el-table-column>
+              <el-table-column label="鎵姏" align="center" prop="torqueForce">
+              </el-table-column>
+              <el-table-column label="瑙掑害" align="center" prop="angle">
+              </el-table-column>
+              <el-table-column label="缁撴灉" align="center" prop="result">
+                <template slot-scope="scope">
+                  <dict-tag :options="dict.type.qualified_status" :value="scope.row.status"/>
+                </template>
+
+              </el-table-column>
+              <el-table-column label="淇濆瓨鏃堕棿" align="center" prop="boxCode">
+              </el-table-column>
+
+            </el-table>
+          </template>
+        </el-tab-pane>
+        <el-tab-pane>
+          <span slot="label"> <b class="el-icon-date"></b>鐩告満妫�娴�</span>
+          <el-empty >
+            <span slot="description">鏆傛棤鏁版嵁</span>
+          </el-empty>
+        </el-tab-pane>
+        <el-tab-pane>
+          <span slot="label"> <b class="el-icon-date"></b>澶栨紡妫�娴�</span>
+          <el-empty >
+            <span slot="description">鏆傛棤鏁版嵁</span>
+          </el-empty>
+        </el-tab-pane>
+        <el-tab-pane>
+          <span slot="label"> <b class="el-icon-date"></b>鏈鸿酱鍔犳敞</span>
+          <el-empty >
+            <span slot="description">鏆傛棤鏁版嵁</span>
+          </el-empty>
+        </el-tab-pane>
+        <el-tab-pane>
+          <span slot="label"> <b class="el-icon-date"></b>宸ヤ綅缁撴灉</span>
+          <el-empty >
+            <span slot="description">鏆傛棤鏁版嵁</span>
+          </el-empty>
+        </el-tab-pane>
+      </el-tabs>
+    </el-card>
+
+
+
+    <!-- 娣诲姞鎴栦慨鏀硅繑淇暟鎹璇濇 -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="鎬绘垚缂栫爜" prop="snCode">
+          <el-input v-model="form.snCode" placeholder="璇疯緭鍏ユ�绘垚缂栫爜" />
+        </el-form-item>
+        <el-form-item label="绠变綋缂栫爜" prop="boxCode">
+          <el-input v-model="form.boxCode" placeholder="璇疯緭鍏ョ浣撶紪鐮�" />
+        </el-form-item>
+        <el-form-item label="宸ュ簭缂栫爜" prop="processesCode">
+          <el-input v-model="form.processesCode" placeholder="璇疯緭鍏ュ伐搴忕紪鐮�" />
+        </el-form-item>
+        <el-form-item label="鎷х揣娆℃暟" prop="tightenFrequency">
+          <el-input v-model="form.tightenFrequency" placeholder="璇疯緭鍏ユ嫥绱ф鏁�" />
+        </el-form-item>
+        <el-form-item label="鎷х揣棰楁暟" prop="tightenPiecesNumber">
+          <el-input v-model="form.tightenPiecesNumber" placeholder="璇疯緭鍏ユ嫥绱ч鏁�" />
+        </el-form-item>
+        <el-form-item label="鎵姏" prop="torqueForce">
+          <el-input v-model="form.torqueForce" placeholder="璇疯緭鍏ユ壄鍔�" />
+        </el-form-item>
+        <el-form-item label="瑙掑害" prop="angle">
+          <el-input v-model="form.angle" placeholder="璇疯緭鍏ヨ搴�" />
+        </el-form-item>
+        <el-form-item label="缁撴灉" prop="result">
+          <el-input v-model="form.result" placeholder="璇疯緭鍏ョ粨鏋�" />
+        </el-form-item>
+        <el-form-item label="鍒涘缓鐢ㄦ埛" prop="createUser">
+          <el-input v-model="form.createUser" placeholder="璇疯緭鍏ュ垱寤虹敤鎴�" />
+        </el-form-item>
+        <el-form-item label="鏇存柊鐢ㄦ埛" prop="updateUser">
+          <el-input v-model="form.updateUser" placeholder="璇疯緭鍏ユ洿鏂扮敤鎴�" />
+        </el-form-item>
+        <el-form-item label="澶囨敞" prop="remarks">
+          <el-input v-model="form.remarks" placeholder="璇疯緭鍏ュ娉�" />
+        </el-form-item>
+        <el-form-item label="棰勭暀瀛楁1" prop="spareField1">
+          <el-input v-model="form.spareField1" placeholder="璇疯緭鍏ラ鐣欏瓧娈�1" />
+        </el-form-item>
+        <el-form-item label="棰勭暀瀛楁2" prop="spareField2">
+          <el-input v-model="form.spareField2" placeholder="璇疯緭鍏ラ鐣欏瓧娈�2" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listRepairRecord, getRepairRecord, delRepairRecord, addRepairRecord, updateRepairRecord } from "@/api/main/rm/repairRecord/repairRecord";
+import { listRepairData, getRepairData, delRepairData, addRepairData, updateRepairData } from "@/api/main/rm/repairData/repairData";
+
+export default {
+  name: "rmRepairData",
+  dicts: ['qualified_status'],
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 杩斾慨鏁版嵁琛ㄦ牸鏁版嵁
+      repairDataList: [],
+      repairRecordList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        snCode: null,
+        boxCode: null,
+        processesCode: null,
+        tightenFrequency: null,
+        tightenPiecesNumber: null,
+        torqueForce: null,
+        angle: null,
+        result: null,
+        createUser: null,
+        updateUser: null,
+        remarks: null,
+        spareField1: null,
+        station: null,
+        spareField2: null
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        id: [
+          { required: true, message: "涓婚敭id涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+      }
+    };
+  },
+  created() {
+    this.getList();
+    this.getRepairRecordList();
+  },
+  methods: {
+    /** 鏌ヨ杩斾慨璁板綍鍒楄〃 */
+    getRepairRecordList() {
+      this.loading = true;
+      listRepairRecord(this.queryParams).then(response => {
+        this.repairRecordList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    /** 鏌ヨ杩斾慨鏁版嵁鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listRepairData(this.queryParams).then(response => {
+        this.repairDataList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        id: null,
+        snCode: null,
+        boxCode: null,
+        processesCode: null,
+        tightenFrequency: null,
+        tightenPiecesNumber: null,
+        torqueForce: null,
+        angle: null,
+        result: null,
+        createUser: null,
+        createTime: null,
+        updateTime: null,
+        updateUser: null,
+        remarks: null,
+        spareField1: null,
+        station: null,
+        spareField2: null
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "娣诲姞杩斾慨鏁版嵁";
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getRepairData(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "淇敼杩斾慨鏁版嵁";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateRepairData(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addRepairData(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎杩斾慨鏁版嵁缂栧彿涓�"' + ids + '"鐨勬暟鎹」锛�').then(function() {
+        return delRepairData(ids);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('rm/repairData/export', {
+        ...this.queryParams
+      }, `repairData_${new Date().getTime()}.xlsx`)
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/main/rm/repairRecord/index.vue b/jcdm-ui/src/views/main/rm/repairRecord/index.vue
new file mode 100644
index 0000000..e2bcb3b
--- /dev/null
+++ b/jcdm-ui/src/views/main/rm/repairRecord/index.vue
@@ -0,0 +1,337 @@
+<template>
+  <div class="app-container">
+    <el-card class ="box-card">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="杩斾慨鏍囪瘑" prop="repairIdentification">
+        <el-input
+          v-model="queryParams.repairIdentification"
+          placeholder="璇疯緭鍏ヨ繑淇爣璇�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="绠变綋缂栫爜" prop="boxCode">
+        <el-input
+          v-model="queryParams.boxCode"
+          placeholder="璇疯緭鍏ョ浣撶紪鐮�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item style="float: right">
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+    </el-card>
+    <el-card style="margin-top: 10px" class="box-card">
+    <el-row :gutter="10" class="mb8">
+<!--      <el-col :span="1.5">-->
+<!--        <el-button-->
+<!--          type="primary"-->
+<!--          plain-->
+<!--          icon="el-icon-plus"-->
+<!--          size="mini"-->
+<!--          @click="handleAdd"-->
+<!--          v-hasPermi="['rm:repairRecord:add']"-->
+<!--        >鏂板</el-button>-->
+<!--      </el-col>-->
+<!--      <el-col :span="1.5">-->
+<!--        <el-button-->
+<!--          type="success"-->
+<!--          plain-->
+<!--          icon="el-icon-edit"-->
+<!--          size="mini"-->
+<!--          :disabled="single"-->
+<!--          @click="handleUpdate"-->
+<!--          v-hasPermi="['rm:repairRecord:edit']"-->
+<!--        >淇敼</el-button>-->
+<!--      </el-col>-->
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['rm:repairRecord:remove']"
+        >鍒犻櫎</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['rm:repairRecord:export']"
+        >瀵煎嚭</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" border :data="repairRecordList" @selection-change="handleSelectionChange" v-if="repairRecordList.length > 0">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="杩斾慨鏍囪瘑" align="center" prop="repairIdentification" />
+      <el-table-column label="绠变綋缂栫爜" align="center" prop="boxCode" />
+      <el-table-column label="宸ュ簭缂栫爜" align="center" prop="processesCode" />
+      <el-table-column label="鍘熺粨鏋�" align="center" prop="originalResult" />
+      <el-table-column label="杩斾慨缁撴灉" align="center" prop="repairResults" />
+      <el-table-column label="鍒涘缓鐢ㄦ埛" align="center" prop="createUser" />
+      <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" />
+      <el-table-column label="杩斾慨鏃堕棿" align="center" prop="repairTime" />
+      <el-table-column label="鐘舵��" align="center" prop="status" width="80">
+        <template slot-scope="scope">
+          <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
+        </template>
+      </el-table-column>
+<!--      <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">-->
+<!--        <template slot-scope="scope">-->
+<!--          <el-button-->
+<!--            size="mini"-->
+<!--            type="text"-->
+<!--            icon="el-icon-edit"-->
+<!--            @click="handleUpdate(scope.row)"-->
+<!--            v-hasPermi="['rm:repairRecord:edit']"-->
+<!--          >淇敼</el-button>-->
+<!--          <el-button-->
+<!--            size="mini"-->
+<!--            type="text"-->
+<!--            icon="el-icon-delete"-->
+<!--            @click="handleDelete(scope.row)"-->
+<!--            v-hasPermi="['rm:repairRecord:remove']"-->
+<!--          >鍒犻櫎</el-button>-->
+<!--        </template>-->
+<!--      </el-table-column>-->
+    </el-table>
+      <el-empty v-else>
+        <span slot="description">鏆傛棤鏁版嵁</span>
+      </el-empty>
+    </el-card>
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 娣诲姞鎴栦慨鏀硅繑淇褰曞璇濇 -->
+    <el-dialog v-dialogpop-up :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="鎬绘垚缂栫爜" prop="snCode">
+          <el-input v-model="form.snCode" placeholder="璇疯緭鍏ユ�绘垚缂栫爜" />
+        </el-form-item>
+        <el-form-item label="杩斾慨鏍囪瘑" prop="repairIdentification">
+          <el-input v-model="form.repairIdentification" placeholder="璇疯緭鍏ヨ繑淇爣璇�" />
+        </el-form-item>
+        <el-form-item label="绠变綋缂栫爜" prop="boxCode">
+          <el-input v-model="form.boxCode" placeholder="璇疯緭鍏ョ浣撶紪鐮�" />
+        </el-form-item>
+        <el-form-item label="宸ュ簭缂栫爜" prop="processesCode">
+          <el-input v-model="form.processesCode" placeholder="璇疯緭鍏ュ伐搴忕紪鐮�" />
+        </el-form-item>
+        <el-form-item label="鍘熺粨鏋�" prop="originalResult">
+          <el-input v-model="form.originalResult" placeholder="璇疯緭鍏ュ師缁撴灉" />
+        </el-form-item>
+        <el-form-item label="鍒涘缓鐢ㄦ埛" prop="createUser">
+          <el-input v-model="form.createUser" placeholder="璇疯緭鍏ュ垱寤虹敤鎴�" />
+        </el-form-item>
+        <el-form-item label="鏇存柊鐢ㄦ埛" prop="updateUser">
+          <el-input v-model="form.updateUser" placeholder="璇疯緭鍏ユ洿鏂扮敤鎴�" />
+        </el-form-item>
+        <el-form-item label="杩斾慨缁撴灉" prop="repairResults">
+          <el-input v-model="form.repairResults" placeholder="璇疯緭鍏ヨ繑淇粨鏋�" />
+        </el-form-item>
+        <el-form-item label="澶囨敞" prop="remarks">
+          <el-input v-model="form.remarks" placeholder="璇疯緭鍏ュ娉�" />
+        </el-form-item>
+        <el-form-item label="棰勭暀瀛楁1" prop="spareField1">
+          <el-input v-model="form.spareField1" placeholder="璇疯緭鍏ラ鐣欏瓧娈�1" />
+        </el-form-item>
+        <el-form-item label="棰勭暀瀛楁2" prop="spareField2">
+          <el-input v-model="form.spareField2" placeholder="璇疯緭鍏ラ鐣欏瓧娈�2" />
+        </el-form-item>
+        <el-form-item label="鐘舵��" prop="status">
+          <el-radio-group v-model="form.status">
+            <el-radio
+              v-for="dict in dict.type.sys_normal_disable"
+              :key="dict.value"
+              :label="dict.value"
+            >{{dict.label}}</el-radio>
+          </el-radio-group>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listRepairRecord, getRepairRecord, delRepairRecord, addRepairRecord, updateRepairRecord } from "@/api/main/rm/repairRecord/repairRecord";
+
+export default {
+  name: "RepairRecord",
+  dicts: ['sys_normal_disable'],
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 杩斾慨璁板綍琛ㄦ牸鏁版嵁
+      repairRecordList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        snCode: null,
+        repairIdentification: null,
+        boxCode: null,
+        processesCode: null,
+        originalResult: null,
+        createUser: null,
+        updateUser: null,
+        repairResults: null,
+        status: null,
+        remarks: null,
+        spareField1: null,
+        spareField2: null
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        id: [
+          { required: true, message: "涓婚敭id涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 鏌ヨ杩斾慨璁板綍鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listRepairRecord(this.queryParams).then(response => {
+        this.repairRecordList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        id: null,
+        snCode: null,
+        repairIdentification: null,
+        boxCode: null,
+        processesCode: null,
+        originalResult: null,
+        createUser: null,
+        createTime: null,
+        updateTime: null,
+        updateUser: null,
+        repairResults: null,
+        status: "0",
+        remarks: null,
+        spareField1: null,
+        repairTime: null,
+        spareField2: null
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "娣诲姞杩斾慨璁板綍";
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getRepairRecord(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "淇敼杩斾慨璁板綍";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateRepairRecord(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addRepairRecord(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎杩斾慨璁板綍缂栧彿涓�"' + ids + '"鐨勬暟鎹」锛�').then(function() {
+        return delRepairRecord(ids);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('rm/repairRecord/export', {
+        ...this.queryParams
+      }, `repairRecord_${new Date().getTime()}.xlsx`)
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/main/sc/stationConf/index.vue b/jcdm-ui/src/views/main/sc/stationConf/index.vue
new file mode 100644
index 0000000..202325f
--- /dev/null
+++ b/jcdm-ui/src/views/main/sc/stationConf/index.vue
@@ -0,0 +1,342 @@
+<template>
+  <div class="app-container">
+    <el-card class="box-card">
+        <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+          <el-form-item label="宸ュ簭缂栧彿" prop="processesCode">
+            <el-input
+              v-model="queryParams.processesCode"
+              placeholder="璇疯緭鍏ュ伐搴忕紪鍙�"
+              clearable
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item label="宸ュ簭鍚嶇О" prop="processesName">
+            <el-input
+              v-model="queryParams.processesName"
+              placeholder="璇疯緭鍏ュ伐搴忓悕绉�"
+              clearable
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item label="IP鍦板潃" prop="ipAddress">
+            <el-input
+              v-model="queryParams.ipAddress"
+              placeholder="璇疯緭鍏P鍦板潃"
+              clearable
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item style="float: right">
+            <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+            <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+          </el-form-item>
+        </el-form>
+    </el-card>
+
+    <el-card style="margin-top: 10px" class="box-card">
+        <el-row :gutter="10" class="mb8">
+          <el-col :span="1.5">
+            <el-button
+              type="primary"
+              plain
+              icon="el-icon-plus"
+              size="mini"
+              @click="handleAdd"
+              v-hasPermi="['sc:stationConf:add']"
+            >鏂板</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="success"
+              plain
+              icon="el-icon-edit"
+              size="mini"
+              :disabled="single"
+              @click="handleUpdate"
+              v-hasPermi="['sc:stationConf:edit']"
+            >淇敼</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="danger"
+              plain
+              icon="el-icon-delete"
+              size="mini"
+              :disabled="multiple"
+              @click="handleDelete"
+              v-hasPermi="['sc:stationConf:remove']"
+            >鍒犻櫎</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="warning"
+              plain
+              icon="el-icon-download"
+              size="mini"
+              @click="handleExport"
+              v-hasPermi="['sc:stationConf:export']"
+            >瀵煎嚭</el-button>
+          </el-col>
+          <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+        </el-row>
+
+        <el-table border v-loading="loading" :data="stationConfList" @selection-change="handleSelectionChange">
+          <el-form-item type="selection" width="55" align="center" >
+          </el-form-item>
+          <el-table-column label="宸ュ簭缂栧彿" align="center" prop="processesCode">
+          </el-table-column>
+          <el-table-column label="宸ュ簭鍚嶇О" align="center" prop="processesName">
+          </el-table-column>
+          <el-table-column label="IP鍦板潃" align="center" prop="ipAddress">
+          </el-table-column>
+          <el-table-column label="澶囨敞" align="center" prop="remarks">
+          </el-table-column>
+          <el-table-column fixed="right" width="200" label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+            <template slot-scope="scope">
+              <el-button
+                size="mini"
+                type="success"
+                plain
+                style="width: 72px"
+                icon="el-icon-edit"
+                @click="handleUpdate(scope.row)"
+                v-hasPermi="['sc:stationConf:edit']"
+              >淇敼</el-button>
+              <el-button
+                size="mini"
+                type="danger"
+                plain
+                style="width: 72px"
+                icon="el-icon-delete"
+                @click="handleDelete(scope.row)"
+                v-hasPermi="['sc:stationConf:remove']"
+              >鍒犻櫎</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+    </el-card>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 娣诲姞鎴栦慨鏀瑰伐浣嶇粓绔厤缃璇濇 -->
+    <el-dialog v-dialogpop-up :title="title" :visible.sync="open" width="500px" append-to-body>
+      <span slot="title">
+        <i class="el-icon-s-order"></i>
+        {{titleName}}
+      </span>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="宸ュ簭缂栧彿" prop="processesCode">
+          <el-select style="width: 100%" @change="handleSelectChangeprocessesCode(form.processesCode)" v-model="form.processesCode" placeholder="璇烽�夋嫨宸ュ簭缂栧彿">
+            <el-option
+              v-for="item in options"
+              :key="item.index"
+              :label="item.processesName"
+              :value="item.processesCode">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="宸ュ簭鍚嶇О" prop="processesName">
+          <el-input  disabled v-model="form.processesName" placeholder="璇疯緭鍏ュ伐搴忓悕绉�" />
+        </el-form-item>
+        <el-form-item label="IP鍦板潃" prop="ipAddress">
+          <el-input v-model="form.ipAddress" placeholder="璇疯緭鍏P鍦板潃" />
+        </el-form-item>
+        <el-form-item label="澶囨敞" prop="remarks">
+          <el-input v-model="form.remarks" placeholder="璇疯緭鍏ュ娉�" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import {listStationConf, getStationConf, delStationConf, addStationConf, updateStationConf} from "@/api/main/sc/stationConf";
+import {listProcesses} from "@/api/main/bs/processes/processes";
+
+export default {
+  name: "StationConf",
+  data() {
+    return {
+      options: [],
+      // 閬僵灞�
+      loading: true,
+      titleName: "",
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 宸ヤ綅缁堢閰嶇疆琛ㄦ牸鏁版嵁
+      stationConfList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        processesCode: null,
+        processesName: null,
+        processesType: null,
+        ipAddress: null,
+        spareField1: null,
+        spareField2: null,
+        spareField3: null,
+        spareField4: null,
+        createUser: null,
+        updateUser: null,
+        remarks: null
+      },
+      processesCodeQueryParams:{
+        pageNum: 1,
+        pageSize: 10,
+        processesCodes: null,
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        id: [
+          { required: true, message: "涓婚敭id涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+      }
+    };
+  },
+  created() {
+    this.getList();
+    this.initProcesses();
+  },
+  methods: {
+
+    handleSelectChangeprocessesCode(selectedOption) {
+      this.processesCodeQueryParams.processesCodes = selectedOption;
+      listProcesses(this.queryParams).then(response => {
+        this.form.processesName = response.rows[0].processesName;
+      });
+    },
+    initProcesses(){
+      listProcesses(this.queryParams).then(response => {
+        this.options = response.rows;
+      });
+    },
+    /** 鏌ヨ宸ヤ綅缁堢閰嶇疆鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listStationConf(this.queryParams).then(response => {
+        this.stationConfList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        id: null,
+        processesCode: null,
+        processesName: null,
+        processesType: null,
+        ipAddress: null,
+        spareField1: null,
+        spareField2: null,
+        spareField3: null,
+        spareField4: null,
+        createUser: null,
+        createTime: null,
+        updateUser: null,
+        updateTime: null,
+        remarks: null
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.titleName = "娣诲姞宸ヤ綅缁堢閰嶇疆";
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getStationConf(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.titleName = "淇敼宸ヤ綅缁堢閰嶇疆";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateStationConf(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addStationConf(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎宸ヤ綅缁堢閰嶇疆缂栧彿涓�"' + ids + '"鐨勬暟鎹」锛�').then(function() {
+        return delStationConf(ids);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('sc/stationConf/export', {
+        ...this.queryParams
+      }, `stationConf_${new Date().getTime()}.xlsx`)
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/monitor/cache/index.vue b/jcdm-ui/src/views/monitor/cache/index.vue
new file mode 100644
index 0000000..8d2f378
--- /dev/null
+++ b/jcdm-ui/src/views/monitor/cache/index.vue
@@ -0,0 +1,148 @@
+<template>
+  <div class="app-container">
+    <el-row>
+      <el-col :span="24" class="card-box">
+        <el-card>
+          <div slot="header"><span><i class="el-icon-monitor"></i> 鍩烘湰淇℃伅</span></div>
+          <div class="el-table el-table--enable-row-hover el-table--medium">
+            <table cellspacing="0" style="width: 100%">
+              <tbody>
+                <tr>
+                  <td class="el-table__cell is-leaf"><div class="cell">Redis鐗堟湰</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.redis_version }}</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell">杩愯妯″紡</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.redis_mode == "standalone" ? "鍗曟満" : "闆嗙兢" }}</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell">绔彛</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.tcp_port }}</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell">瀹㈡埛绔暟</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.connected_clients }}</div></td>
+                </tr>
+                <tr>
+                  <td class="el-table__cell is-leaf"><div class="cell">杩愯鏃堕棿(澶�)</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.uptime_in_days }}</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell">浣跨敤鍐呭瓨</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.used_memory_human }}</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell">浣跨敤CPU</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ parseFloat(cache.info.used_cpu_user_children).toFixed(2) }}</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell">鍐呭瓨閰嶇疆</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.maxmemory_human }}</div></td>
+                </tr>
+                <tr>
+                  <td class="el-table__cell is-leaf"><div class="cell">AOF鏄惁寮�鍚�</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.aof_enabled == "0" ? "鍚�" : "鏄�" }}</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell">RDB鏄惁鎴愬姛</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.rdb_last_bgsave_status }}</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell">Key鏁伴噺</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.dbSize">{{ cache.dbSize }} </div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell">缃戠粶鍏ュ彛/鍑哄彛</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.instantaneous_input_kbps }}kps/{{cache.info.instantaneous_output_kbps}}kps</div></td>
+                </tr>
+              </tbody>
+            </table>
+          </div>
+        </el-card>
+      </el-col>
+
+      <el-col :span="12" class="card-box">
+        <el-card>
+          <div slot="header"><span><i class="el-icon-pie-chart"></i> 鍛戒护缁熻</span></div>
+          <div class="el-table el-table--enable-row-hover el-table--medium">
+            <div ref="commandstats" style="height: 420px" />
+          </div>
+        </el-card>
+      </el-col>
+
+      <el-col :span="12" class="card-box">
+        <el-card>
+          <div slot="header"><span><i class="el-icon-odometer"></i> 鍐呭瓨淇℃伅</span></div>
+          <div class="el-table el-table--enable-row-hover el-table--medium">
+            <div ref="usedmemory" style="height: 420px" />
+          </div>
+        </el-card>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import { getCache } from "@/api/monitor/cache";
+import * as echarts from "echarts";
+
+export default {
+  name: "Cache",
+  data() {
+    return {
+      // 缁熻鍛戒护淇℃伅
+      commandstats: null,
+      // 浣跨敤鍐呭瓨
+      usedmemory: null,
+      // cache淇℃伅
+      cache: []
+    }
+  },
+  created() {
+    this.getList();
+    this.openLoading();
+  },
+  methods: {
+    /** 鏌ョ紦瀛樿淇℃伅 */
+    getList() {
+      getCache().then((response) => {
+        this.cache = response.data;
+        this.$modal.closeLoading();
+
+        this.commandstats = echarts.init(this.$refs.commandstats, "macarons");
+        this.commandstats.setOption({
+          tooltip: {
+            trigger: "item",
+            formatter: "{a} <br/>{b} : {c} ({d}%)",
+          },
+          series: [
+            {
+              name: "鍛戒护",
+              type: "pie",
+              roseType: "radius",
+              radius: [15, 95],
+              center: ["50%", "38%"],
+              data: response.data.commandStats,
+              animationEasing: "cubicInOut",
+              animationDuration: 1000,
+            }
+          ]
+        });
+        this.usedmemory = echarts.init(this.$refs.usedmemory, "macarons");
+        this.usedmemory.setOption({
+          tooltip: {
+            formatter: "{b} <br/>{a} : " + this.cache.info.used_memory_human,
+          },
+          series: [
+            {
+              name: "宄板��",
+              type: "gauge",
+              min: 0,
+              max: 1000,
+              detail: {
+                formatter: this.cache.info.used_memory_human,
+              },
+              data: [
+                {
+                  value: parseFloat(this.cache.info.used_memory_human),
+                  name: "鍐呭瓨娑堣��",
+                }
+              ]
+            }
+          ]
+        });
+        window.addEventListener("resize", () => {
+          this.commandstats.resize();
+          this.usedmemory.resize();
+        });
+      });
+    },
+    // 鎵撳紑鍔犺浇灞�
+    openLoading() {
+      this.$modal.loading("姝e湪鍔犺浇缂撳瓨鐩戞帶鏁版嵁锛岃绋嶅�欙紒");
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/monitor/cache/list.vue b/jcdm-ui/src/views/monitor/cache/list.vue
new file mode 100644
index 0000000..29a7c74
--- /dev/null
+++ b/jcdm-ui/src/views/monitor/cache/list.vue
@@ -0,0 +1,241 @@
+<template>
+  <div class="app-container">
+    <el-row :gutter="10">
+      <el-col :span="8">
+        <el-card style="height: calc(100vh - 125px)">
+          <div slot="header">
+            <span><i class="el-icon-collection"></i> 缂撳瓨鍒楄〃</span>
+            <el-button
+              style="float: right; padding: 3px 0"
+              type="text"
+              icon="el-icon-refresh-right"
+              @click="refreshCacheNames()"
+            ></el-button>
+          </div>
+          <el-table
+            v-loading="loading"
+            :data="cacheNames"
+            :height="tableHeight"
+            highlight-current-row
+            @row-click="getCacheKeys"
+            style="width: 100%"
+          >
+            <el-table-column
+              label="搴忓彿"
+              width="60"
+              type="index"
+            ></el-table-column>
+
+            <el-table-column
+              label="缂撳瓨鍚嶇О"
+              align="center"
+              prop="cacheName"
+              :show-overflow-tooltip="true"
+              :formatter="nameFormatter"
+            ></el-table-column>
+
+            <el-table-column
+              label="澶囨敞"
+              align="center"
+              prop="remark"
+              :show-overflow-tooltip="true"
+            />
+            <el-table-column
+              label="鎿嶄綔"
+              width="60"
+              align="center"
+              class-name="small-padding fixed-width"
+            >
+              <template slot-scope="scope">
+                <el-button
+                  size="mini"
+                  type="text"
+                  icon="el-icon-delete"
+                  @click="handleClearCacheName(scope.row)"
+                ></el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+        </el-card>
+      </el-col>
+
+      <el-col :span="8">
+        <el-card style="height: calc(100vh - 125px)">
+          <div slot="header">
+            <span><i class="el-icon-key"></i> 閿悕鍒楄〃</span>
+            <el-button
+              style="float: right; padding: 3px 0"
+              type="text"
+              icon="el-icon-refresh-right"
+              @click="refreshCacheKeys()"
+            ></el-button>
+          </div>
+          <el-table
+            v-loading="subLoading"
+            :data="cacheKeys"
+            :height="tableHeight"
+            highlight-current-row
+            @row-click="handleCacheValue"
+            style="width: 100%"
+          >
+            <el-table-column
+              label="搴忓彿"
+              width="60"
+              type="index"
+            ></el-table-column>
+            <el-table-column
+              label="缂撳瓨閿悕"
+              align="center"
+              :show-overflow-tooltip="true"
+              :formatter="keyFormatter"
+            >
+            </el-table-column>
+            <el-table-column
+              label="鎿嶄綔"
+              width="60"
+              align="center"
+              class-name="small-padding fixed-width"
+            >
+              <template slot-scope="scope">
+                <el-button
+                  size="mini"
+                  type="text"
+                  icon="el-icon-delete"
+                  @click="handleClearCacheKey(scope.row)"
+                ></el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+        </el-card>
+      </el-col>
+
+      <el-col :span="8">
+        <el-card :bordered="false" style="height: calc(100vh - 125px)">
+          <div slot="header">
+            <span><i class="el-icon-document"></i> 缂撳瓨鍐呭</span>
+            <el-button
+              style="float: right; padding: 3px 0"
+              type="text"
+              icon="el-icon-refresh-right"
+              @click="handleClearCacheAll()"
+              >娓呯悊鍏ㄩ儴</el-button
+            >
+          </div>
+          <el-form :model="cacheForm">
+            <el-row :gutter="32">
+              <el-col :offset="1" :span="22">
+                <el-form-item label="缂撳瓨鍚嶇О:" prop="cacheName">
+                  <el-input v-model="cacheForm.cacheName" :readOnly="true" />
+                </el-form-item>
+              </el-col>
+              <el-col :offset="1" :span="22">
+                <el-form-item label="缂撳瓨閿悕:" prop="cacheKey">
+                  <el-input v-model="cacheForm.cacheKey" :readOnly="true" />
+                </el-form-item>
+              </el-col>
+              <el-col :offset="1" :span="22">
+                <el-form-item label="缂撳瓨鍐呭:" prop="cacheValue">
+                  <el-input
+                    v-model="cacheForm.cacheValue"
+                    type="textarea"
+                    :rows="8"
+                    :readOnly="true"
+                  />
+                </el-form-item>
+              </el-col>
+            </el-row>
+          </el-form>
+        </el-card>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import { listCacheName, listCacheKey, getCacheValue, clearCacheName, clearCacheKey, clearCacheAll } from "@/api/monitor/cache";
+
+export default {
+  name: "CacheList",
+  data() {
+    return {
+      cacheNames: [],
+      cacheKeys: [],
+      cacheForm: {},
+      loading: true,
+      subLoading: false,
+      nowCacheName: "",
+      tableHeight: window.innerHeight - 200
+    };
+  },
+  created() {
+    this.getCacheNames();
+  },
+  methods: {
+    /** 鏌ヨ缂撳瓨鍚嶇О鍒楄〃 */
+    getCacheNames() {
+      this.loading = true;
+      listCacheName().then(response => {
+        this.cacheNames = response.data;
+        this.loading = false;
+      });
+    },
+    /** 鍒锋柊缂撳瓨鍚嶇О鍒楄〃 */
+    refreshCacheNames() {
+      this.getCacheNames();
+      this.$modal.msgSuccess("鍒锋柊缂撳瓨鍒楄〃鎴愬姛");
+    },
+    /** 娓呯悊鎸囧畾鍚嶇О缂撳瓨 */
+    handleClearCacheName(row) {
+      clearCacheName(row.cacheName).then(response => {
+        this.$modal.msgSuccess("娓呯悊缂撳瓨鍚嶇О[" + row.cacheName + "]鎴愬姛");
+        this.getCacheKeys();
+      });
+    },
+    /** 鏌ヨ缂撳瓨閿悕鍒楄〃 */
+    getCacheKeys(row) {
+      const cacheName = row !== undefined ? row.cacheName : this.nowCacheName;
+      if (cacheName === "") {
+        return;
+      }
+      this.subLoading = true;
+      listCacheKey(cacheName).then(response => {
+        this.cacheKeys = response.data;
+        this.subLoading = false;
+        this.nowCacheName = cacheName;
+      });
+    },
+    /** 鍒锋柊缂撳瓨閿悕鍒楄〃 */
+    refreshCacheKeys() {
+      this.getCacheKeys();
+      this.$modal.msgSuccess("鍒锋柊閿悕鍒楄〃鎴愬姛");
+    },
+    /** 娓呯悊鎸囧畾閿悕缂撳瓨 */
+    handleClearCacheKey(cacheKey) {
+      clearCacheKey(cacheKey).then(response => {
+        this.$modal.msgSuccess("娓呯悊缂撳瓨閿悕[" + cacheKey + "]鎴愬姛");
+        this.getCacheKeys();
+      });
+    },
+    /** 鍒楄〃鍓嶇紑鍘婚櫎 */
+    nameFormatter(row) {
+      return row.cacheName.replace(":", "");
+    },
+    /** 閿悕鍓嶇紑鍘婚櫎 */
+    keyFormatter(cacheKey) {
+      return cacheKey.replace(this.nowCacheName, "");
+    },
+    /** 鏌ヨ缂撳瓨鍐呭璇︾粏 */
+    handleCacheValue(cacheKey) {
+      getCacheValue(this.nowCacheName, cacheKey).then(response => {
+        this.cacheForm = response.data;
+      });
+    },
+    /** 娓呯悊鍏ㄩ儴缂撳瓨 */
+    handleClearCacheAll() {
+      clearCacheAll().then(response => {
+        this.$modal.msgSuccess("娓呯悊鍏ㄩ儴缂撳瓨鎴愬姛");
+      });
+    }
+  },
+};
+</script>
diff --git a/jcdm-ui/src/views/monitor/druid/index.vue b/jcdm-ui/src/views/monitor/druid/index.vue
new file mode 100644
index 0000000..c6ad585
--- /dev/null
+++ b/jcdm-ui/src/views/monitor/druid/index.vue
@@ -0,0 +1,15 @@
+<template>
+  <i-frame :src="url" />
+</template>
+<script>
+import iFrame from "@/components/iFrame/index";
+export default {
+  name: "Druid",
+  components: { iFrame },
+  data() {
+    return {
+      url: process.env.VUE_APP_BASE_API + "/druid/login.html"
+    };
+  },
+};
+</script>
diff --git a/jcdm-ui/src/views/monitor/job/index.vue b/jcdm-ui/src/views/monitor/job/index.vue
new file mode 100644
index 0000000..131ec45
--- /dev/null
+++ b/jcdm-ui/src/views/monitor/job/index.vue
@@ -0,0 +1,513 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="浠诲姟鍚嶇О" prop="jobName">
+        <el-input
+          v-model="queryParams.jobName"
+          placeholder="璇疯緭鍏ヤ换鍔″悕绉�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="浠诲姟缁勫悕" prop="jobGroup">
+        <el-select v-model="queryParams.jobGroup" placeholder="璇烽�夋嫨浠诲姟缁勫悕" clearable>
+          <el-option
+            v-for="dict in dict.type.sys_job_group"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="浠诲姟鐘舵��" prop="status">
+        <el-select v-model="queryParams.status" placeholder="璇烽�夋嫨浠诲姟鐘舵��" clearable>
+          <el-option
+            v-for="dict in dict.type.sys_job_status"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['monitor:job:add']"
+        >鏂板</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['monitor:job:edit']"
+        >淇敼</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['monitor:job:remove']"
+        >鍒犻櫎</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['monitor:job:export']"
+        >瀵煎嚭</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="info"
+          plain
+          icon="el-icon-s-operation"
+          size="mini"
+          @click="handleJobLog"
+          v-hasPermi="['monitor:job:query']"
+        >鏃ュ織</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="jobList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="浠诲姟缂栧彿" width="100" align="center" prop="jobId" />
+      <el-table-column label="浠诲姟鍚嶇О" align="center" prop="jobName" :show-overflow-tooltip="true" />
+      <el-table-column label="浠诲姟缁勫悕" align="center" prop="jobGroup">
+        <template slot-scope="scope">
+          <dict-tag :options="dict.type.sys_job_group" :value="scope.row.jobGroup"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="璋冪敤鐩爣瀛楃涓�" align="center" prop="invokeTarget" :show-overflow-tooltip="true" />
+      <el-table-column label="cron鎵ц琛ㄨ揪寮�" align="center" prop="cronExpression" :show-overflow-tooltip="true" />
+      <el-table-column label="鐘舵��" align="center">
+        <template slot-scope="scope">
+          <el-switch
+            v-model="scope.row.status"
+            active-value="0"
+            inactive-value="1"
+            @change="handleStatusChange(scope.row)"
+          ></el-switch>
+        </template>
+      </el-table-column>
+      <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['monitor:job:edit']"
+          >淇敼</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['monitor:job:remove']"
+          >鍒犻櫎</el-button>
+          <el-dropdown size="mini" @command="(command) => handleCommand(command, scope.row)" v-hasPermi="['monitor:job:changeStatus', 'monitor:job:query']">
+            <el-button size="mini" type="text" icon="el-icon-d-arrow-right">鏇村</el-button>
+            <el-dropdown-menu slot="dropdown">
+              <el-dropdown-item command="handleRun" icon="el-icon-caret-right"
+                v-hasPermi="['monitor:job:changeStatus']">鎵ц涓�娆�</el-dropdown-item>
+              <el-dropdown-item command="handleView" icon="el-icon-view"
+                v-hasPermi="['monitor:job:query']">浠诲姟璇︾粏</el-dropdown-item>
+              <el-dropdown-item command="handleJobLog" icon="el-icon-s-operation"
+                v-hasPermi="['monitor:job:query']">璋冨害鏃ュ織</el-dropdown-item>
+            </el-dropdown-menu>
+          </el-dropdown>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 娣诲姞鎴栦慨鏀瑰畾鏃朵换鍔″璇濇 -->
+    <el-dialog :title="title" :visible.sync="open" width="800px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="120px">
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="浠诲姟鍚嶇О" prop="jobName">
+              <el-input v-model="form.jobName" placeholder="璇疯緭鍏ヤ换鍔″悕绉�" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="浠诲姟鍒嗙粍" prop="jobGroup">
+              <el-select v-model="form.jobGroup" placeholder="璇烽�夋嫨浠诲姟鍒嗙粍">
+                <el-option
+                  v-for="dict in dict.type.sys_job_group"
+                  :key="dict.value"
+                  :label="dict.label"
+                  :value="dict.value"
+                ></el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="24">
+            <el-form-item prop="invokeTarget">
+              <span slot="label">
+                璋冪敤鏂规硶
+                <el-tooltip placement="top">
+                  <div slot="content">
+                    Bean璋冪敤绀轰緥锛歳yTask.ryParams('ry')
+                    <br />Class绫昏皟鐢ㄧず渚嬶細com.jcdm.quartz.task.RyTask.ryParams('ry')
+                    <br />鍙傛暟璇存槑锛氭敮鎸佸瓧绗︿覆锛屽竷灏旂被鍨嬶紝闀挎暣鍨嬶紝娴偣鍨嬶紝鏁村瀷
+                  </div>
+                  <i class="el-icon-question"></i>
+                </el-tooltip>
+              </span>
+              <el-input v-model="form.invokeTarget" placeholder="璇疯緭鍏ヨ皟鐢ㄧ洰鏍囧瓧绗︿覆" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="24">
+            <el-form-item label="cron琛ㄨ揪寮�" prop="cronExpression">
+              <el-input v-model="form.cronExpression" placeholder="璇疯緭鍏ron鎵ц琛ㄨ揪寮�">
+                <template slot="append">
+                  <el-button type="primary" @click="handleShowCron">
+                    鐢熸垚琛ㄨ揪寮�
+                    <i class="el-icon-time el-icon--right"></i>
+                  </el-button>
+                </template>
+              </el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="24" v-if="form.jobId !== undefined">
+            <el-form-item label="鐘舵��">
+              <el-radio-group v-model="form.status">
+                <el-radio
+                  v-for="dict in dict.type.sys_job_status"
+                  :key="dict.value"
+                  :label="dict.value"
+                >{{dict.label}}</el-radio>
+              </el-radio-group>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鎵ц绛栫暐" prop="misfirePolicy">
+              <el-radio-group v-model="form.misfirePolicy" size="small">
+                <el-radio-button label="1">绔嬪嵆鎵ц</el-radio-button>
+                <el-radio-button label="2">鎵ц涓�娆�</el-radio-button>
+                <el-radio-button label="3">鏀惧純鎵ц</el-radio-button>
+              </el-radio-group>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鏄惁骞跺彂" prop="concurrent">
+              <el-radio-group v-model="form.concurrent" size="small">
+                <el-radio-button label="0">鍏佽</el-radio-button>
+                <el-radio-button label="1">绂佹</el-radio-button>
+              </el-radio-group>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+
+    <el-dialog title="Cron琛ㄨ揪寮忕敓鎴愬櫒" :visible.sync="openCron" append-to-body destroy-on-close class="scrollbar">
+      <crontab @hide="openCron=false" @fill="crontabFill" :expression="expression"></crontab>
+    </el-dialog>
+
+    <!-- 浠诲姟鏃ュ織璇︾粏 -->
+    <el-dialog title="浠诲姟璇︾粏" :visible.sync="openView" width="700px" append-to-body>
+      <el-form ref="form" :model="form" label-width="120px" size="mini">
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="浠诲姟缂栧彿锛�">{{ form.jobId }}</el-form-item>
+            <el-form-item label="浠诲姟鍚嶇О锛�">{{ form.jobName }}</el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="浠诲姟鍒嗙粍锛�">{{ jobGroupFormat(form) }}</el-form-item>
+            <el-form-item label="鍒涘缓鏃堕棿锛�">{{ form.createTime }}</el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="cron琛ㄨ揪寮忥細">{{ form.cronExpression }}</el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="涓嬫鎵ц鏃堕棿锛�">{{ parseTime(form.nextValidTime) }}</el-form-item>
+          </el-col>
+          <el-col :span="24">
+            <el-form-item label="璋冪敤鐩爣鏂规硶锛�">{{ form.invokeTarget }}</el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="浠诲姟鐘舵�侊細">
+              <div v-if="form.status == 0">姝e父</div>
+              <div v-else-if="form.status == 1">鏆傚仠</div>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鏄惁骞跺彂锛�">
+              <div v-if="form.concurrent == 0">鍏佽</div>
+              <div v-else-if="form.concurrent == 1">绂佹</div>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鎵ц绛栫暐锛�">
+              <div v-if="form.misfirePolicy == 0">榛樿绛栫暐</div>
+              <div v-else-if="form.misfirePolicy == 1">绔嬪嵆鎵ц</div>
+              <div v-else-if="form.misfirePolicy == 2">鎵ц涓�娆�</div>
+              <div v-else-if="form.misfirePolicy == 3">鏀惧純鎵ц</div>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="openView = false">鍏� 闂�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listJob, getJob, delJob, addJob, updateJob, runJob, changeJobStatus } from "@/api/monitor/job";
+import Crontab from '@/components/Crontab'
+
+export default {
+  components: { Crontab },
+  name: "Job",
+  dicts: ['sys_job_group', 'sys_job_status'],
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 瀹氭椂浠诲姟琛ㄦ牸鏁版嵁
+      jobList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏄惁鏄剧ず璇︾粏寮瑰嚭灞�
+      openView: false,
+      // 鏄惁鏄剧ずCron琛ㄨ揪寮忓脊鍑哄眰
+      openCron: false,
+      // 浼犲叆鐨勮〃杈惧紡
+      expression: "",
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        jobName: undefined,
+        jobGroup: undefined,
+        status: undefined
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        jobName: [
+          { required: true, message: "浠诲姟鍚嶇О涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        invokeTarget: [
+          { required: true, message: "璋冪敤鐩爣瀛楃涓蹭笉鑳戒负绌�", trigger: "blur" }
+        ],
+        cronExpression: [
+          { required: true, message: "cron鎵ц琛ㄨ揪寮忎笉鑳戒负绌�", trigger: "blur" }
+        ]
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 鏌ヨ瀹氭椂浠诲姟鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listJob(this.queryParams).then(response => {
+        this.jobList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 浠诲姟缁勫悕瀛楀吀缈昏瘧
+    jobGroupFormat(row, column) {
+      return this.selectDictLabel(this.dict.type.sys_job_group, row.jobGroup);
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        jobId: undefined,
+        jobName: undefined,
+        jobGroup: undefined,
+        invokeTarget: undefined,
+        cronExpression: undefined,
+        misfirePolicy: 1,
+        concurrent: 1,
+        status: "0"
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.jobId);
+      this.single = selection.length != 1;
+      this.multiple = !selection.length;
+    },
+    // 鏇村鎿嶄綔瑙﹀彂
+    handleCommand(command, row) {
+      switch (command) {
+        case "handleRun":
+          this.handleRun(row);
+          break;
+        case "handleView":
+          this.handleView(row);
+          break;
+        case "handleJobLog":
+          this.handleJobLog(row);
+          break;
+        default:
+          break;
+      }
+    },
+    // 浠诲姟鐘舵�佷慨鏀�
+    handleStatusChange(row) {
+      let text = row.status === "0" ? "鍚敤" : "鍋滅敤";
+      this.$modal.confirm('纭瑕�"' + text + '""' + row.jobName + '"浠诲姟鍚楋紵').then(function() {
+        return changeJobStatus(row.jobId, row.status);
+      }).then(() => {
+        this.$modal.msgSuccess(text + "鎴愬姛");
+      }).catch(function() {
+        row.status = row.status === "0" ? "1" : "0";
+      });
+    },
+    /* 绔嬪嵆鎵ц涓�娆� */
+    handleRun(row) {
+      this.$modal.confirm('纭瑕佺珛鍗虫墽琛屼竴娆�"' + row.jobName + '"浠诲姟鍚楋紵').then(function() {
+        return runJob(row.jobId, row.jobGroup);
+      }).then(() => {
+        this.$modal.msgSuccess("鎵ц鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 浠诲姟璇︾粏淇℃伅 */
+    handleView(row) {
+      getJob(row.jobId).then(response => {
+        this.form = response.data;
+        this.openView = true;
+      });
+    },
+    /** cron琛ㄨ揪寮忔寜閽搷浣� */
+    handleShowCron() {
+      this.expression = this.form.cronExpression;
+      this.openCron = true;
+    },
+    /** 纭畾鍚庡洖浼犲�� */
+    crontabFill(value) {
+      this.form.cronExpression = value;
+    },
+    /** 浠诲姟鏃ュ織鍒楄〃鏌ヨ */
+    handleJobLog(row) {
+      const jobId = row.jobId || 0;
+      this.$router.push('/monitor/job-log/index/' + jobId)
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "娣诲姞浠诲姟";
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.reset();
+      const jobId = row.jobId || this.ids;
+      getJob(jobId).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "淇敼浠诲姟";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm: function() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.jobId != undefined) {
+            updateJob(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addJob(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const jobIds = row.jobId || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎瀹氭椂浠诲姟缂栧彿涓�"' + jobIds + '"鐨勬暟鎹」锛�').then(function() {
+        return delJob(jobIds);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('monitor/job/export', {
+        ...this.queryParams
+      }, `job_${new Date().getTime()}.xlsx`)
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/monitor/job/log.vue b/jcdm-ui/src/views/monitor/job/log.vue
new file mode 100644
index 0000000..60bee1d
--- /dev/null
+++ b/jcdm-ui/src/views/monitor/job/log.vue
@@ -0,0 +1,295 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="浠诲姟鍚嶇О" prop="jobName">
+        <el-input
+          v-model="queryParams.jobName"
+          placeholder="璇疯緭鍏ヤ换鍔″悕绉�"
+          clearable
+          style="width: 240px"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="浠诲姟缁勫悕" prop="jobGroup">
+        <el-select
+          v-model="queryParams.jobGroup"
+          placeholder="璇烽�夋嫨浠诲姟缁勫悕"
+          clearable
+          style="width: 240px"
+        >
+          <el-option
+            v-for="dict in dict.type.sys_job_group"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="鎵ц鐘舵��" prop="status">
+        <el-select
+          v-model="queryParams.status"
+          placeholder="璇烽�夋嫨鎵ц鐘舵��"
+          clearable
+          style="width: 240px"
+        >
+          <el-option
+            v-for="dict in dict.type.sys_common_status"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="鎵ц鏃堕棿">
+        <el-date-picker
+          v-model="dateRange"
+          style="width: 240px"
+          value-format="yyyy-MM-dd"
+          type="daterange"
+          range-separator="-"
+          start-placeholder="寮�濮嬫棩鏈�"
+          end-placeholder="缁撴潫鏃ユ湡"
+        ></el-date-picker>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['monitor:job:remove']"
+        >鍒犻櫎</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          @click="handleClean"
+          v-hasPermi="['monitor:job:remove']"
+        >娓呯┖</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['monitor:job:export']"
+        >瀵煎嚭</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-close"
+          size="mini"
+          @click="handleClose"
+        >鍏抽棴</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="jobLogList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="鏃ュ織缂栧彿" width="80" align="center" prop="jobLogId" />
+      <el-table-column label="浠诲姟鍚嶇О" align="center" prop="jobName" :show-overflow-tooltip="true" />
+      <el-table-column label="浠诲姟缁勫悕" align="center" prop="jobGroup" :show-overflow-tooltip="true">
+        <template slot-scope="scope">
+          <dict-tag :options="dict.type.sys_job_group" :value="scope.row.jobGroup"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="璋冪敤鐩爣瀛楃涓�" align="center" prop="invokeTarget" :show-overflow-tooltip="true" />
+      <el-table-column label="鏃ュ織淇℃伅" align="center" prop="jobMessage" :show-overflow-tooltip="true" />
+      <el-table-column label="鎵ц鐘舵��" align="center" prop="status">
+        <template slot-scope="scope">
+          <dict-tag :options="dict.type.sys_common_status" :value="scope.row.status"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="鎵ц鏃堕棿" align="center" prop="createTime" width="180">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-view"
+            @click="handleView(scope.row)"
+            v-hasPermi="['monitor:job:query']"
+          >璇︾粏</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 璋冨害鏃ュ織璇︾粏 -->
+    <el-dialog title="璋冨害鏃ュ織璇︾粏" :visible.sync="open" width="700px" append-to-body>
+      <el-form ref="form" :model="form" label-width="100px" size="mini">
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="鏃ュ織搴忓彿锛�">{{ form.jobLogId }}</el-form-item>
+            <el-form-item label="浠诲姟鍚嶇О锛�">{{ form.jobName }}</el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="浠诲姟鍒嗙粍锛�">{{ form.jobGroup }}</el-form-item>
+            <el-form-item label="鎵ц鏃堕棿锛�">{{ form.createTime }}</el-form-item>
+          </el-col>
+          <el-col :span="24">
+            <el-form-item label="璋冪敤鏂规硶锛�">{{ form.invokeTarget }}</el-form-item>
+          </el-col>
+          <el-col :span="24">
+            <el-form-item label="鏃ュ織淇℃伅锛�">{{ form.jobMessage }}</el-form-item>
+          </el-col>
+          <el-col :span="24">
+            <el-form-item label="鎵ц鐘舵�侊細">
+              <div v-if="form.status == 0">姝e父</div>
+              <div v-else-if="form.status == 1">澶辫触</div>
+            </el-form-item>
+          </el-col>
+          <el-col :span="24">
+            <el-form-item label="寮傚父淇℃伅锛�" v-if="form.status == 1">{{ form.exceptionInfo }}</el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="open = false">鍏� 闂�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { getJob} from "@/api/monitor/job";
+import { listJobLog, delJobLog, cleanJobLog } from "@/api/monitor/jobLog";
+
+export default {
+  name: "JobLog",
+  dicts: ['sys_common_status', 'sys_job_group'],
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 璋冨害鏃ュ織琛ㄦ牸鏁版嵁
+      jobLogList: [],
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏃ユ湡鑼冨洿
+      dateRange: [],
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        jobName: undefined,
+        jobGroup: undefined,
+        status: undefined
+      }
+    };
+  },
+  created() {
+    const jobId = this.$route.params && this.$route.params.jobId;
+    if (jobId !== undefined && jobId != 0) {
+      getJob(jobId).then(response => {
+        this.queryParams.jobName = response.data.jobName;
+        this.queryParams.jobGroup = response.data.jobGroup;
+        this.getList();
+      });
+    } else {
+      this.getList();
+    }
+  },
+  methods: {
+    /** 鏌ヨ璋冨害鏃ュ織鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listJobLog(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
+          this.jobLogList = response.rows;
+          this.total = response.total;
+          this.loading = false;
+        }
+      );
+    },
+    // 杩斿洖鎸夐挳
+    handleClose() {
+      const obj = { path: "/monitor/job" };
+      this.$tab.closeOpenPage(obj);
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.dateRange = [];
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.jobLogId);
+      this.multiple = !selection.length;
+    },
+    /** 璇︾粏鎸夐挳鎿嶄綔 */
+    handleView(row) {
+      this.open = true;
+      this.form = row;
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const jobLogIds = this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎璋冨害鏃ュ織缂栧彿涓�"' + jobLogIds + '"鐨勬暟鎹」锛�').then(function() {
+        return delJobLog(jobLogIds);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 娓呯┖鎸夐挳鎿嶄綔 */
+    handleClean() {
+      this.$modal.confirm('鏄惁纭娓呯┖鎵�鏈夎皟搴︽棩蹇楁暟鎹」锛�').then(function() {
+        return cleanJobLog();
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("娓呯┖鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('/monitor/jobLog/export', {
+        ...this.queryParams
+      }, `log_${new Date().getTime()}.xlsx`)
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/monitor/logininfor/index.vue b/jcdm-ui/src/views/monitor/logininfor/index.vue
new file mode 100644
index 0000000..d6af834
--- /dev/null
+++ b/jcdm-ui/src/views/monitor/logininfor/index.vue
@@ -0,0 +1,246 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="鐧诲綍鍦板潃" prop="ipaddr">
+        <el-input
+          v-model="queryParams.ipaddr"
+          placeholder="璇疯緭鍏ョ櫥褰曞湴鍧�"
+          clearable
+          style="width: 240px;"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="鐢ㄦ埛鍚嶇О" prop="userName">
+        <el-input
+          v-model="queryParams.userName"
+          placeholder="璇疯緭鍏ョ敤鎴峰悕绉�"
+          clearable
+          style="width: 240px;"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="鐘舵��" prop="status">
+        <el-select
+          v-model="queryParams.status"
+          placeholder="鐧诲綍鐘舵��"
+          clearable
+          style="width: 240px"
+        >
+          <el-option
+            v-for="dict in dict.type.sys_common_status"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="鐧诲綍鏃堕棿">
+        <el-date-picker
+          v-model="dateRange"
+          style="width: 240px"
+          value-format="yyyy-MM-dd HH:mm:ss"
+          type="daterange"
+          range-separator="-"
+          start-placeholder="寮�濮嬫棩鏈�"
+          end-placeholder="缁撴潫鏃ユ湡"
+          :default-time="['00:00:00', '23:59:59']"
+        ></el-date-picker>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['monitor:logininfor:remove']"
+        >鍒犻櫎</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          @click="handleClean"
+          v-hasPermi="['monitor:logininfor:remove']"
+        >娓呯┖</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-unlock"
+          size="mini"
+          :disabled="single"
+          @click="handleUnlock"
+          v-hasPermi="['monitor:logininfor:unlock']"
+        >瑙i攣</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['monitor:logininfor:export']"
+        >瀵煎嚭</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table ref="tables" v-loading="loading" :data="list" @selection-change="handleSelectionChange" :default-sort="defaultSort" @sort-change="handleSortChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="璁块棶缂栧彿" align="center" prop="infoId" />
+      <el-table-column label="鐢ㄦ埛鍚嶇О" align="center" prop="userName" :show-overflow-tooltip="true" sortable="custom" :sort-orders="['descending', 'ascending']" />
+      <el-table-column label="鐧诲綍鍦板潃" align="center" prop="ipaddr" width="130" :show-overflow-tooltip="true" />
+      <el-table-column label="鐧诲綍鍦扮偣" align="center" prop="loginLocation" :show-overflow-tooltip="true" />
+      <el-table-column label="娴忚鍣�" align="center" prop="browser" :show-overflow-tooltip="true" />
+      <el-table-column label="鎿嶄綔绯荤粺" align="center" prop="os" />
+      <el-table-column label="鐧诲綍鐘舵��" align="center" prop="status">
+        <template slot-scope="scope">
+          <dict-tag :options="dict.type.sys_common_status" :value="scope.row.status"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="鎿嶄綔淇℃伅" align="center" prop="msg" :show-overflow-tooltip="true" />
+      <el-table-column label="鐧诲綍鏃ユ湡" align="center" prop="loginTime" sortable="custom" :sort-orders="['descending', 'ascending']" width="180">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.loginTime) }}</span>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+  </div>
+</template>
+
+<script>
+import { list, delLogininfor, cleanLogininfor, unlockLogininfor } from "@/api/monitor/logininfor";
+
+export default {
+  name: "Logininfor",
+  dicts: ['sys_common_status'],
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 閫夋嫨鐢ㄦ埛鍚�
+      selectName: "",
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 琛ㄦ牸鏁版嵁
+      list: [],
+      // 鏃ユ湡鑼冨洿
+      dateRange: [],
+      // 榛樿鎺掑簭
+      defaultSort: {prop: 'loginTime', order: 'descending'},
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        ipaddr: undefined,
+        userName: undefined,
+        status: undefined
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 鏌ヨ鐧诲綍鏃ュ織鍒楄〃 */
+    getList() {
+      this.loading = true;
+      list(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
+          this.list = response.rows;
+          this.total = response.total;
+          this.loading = false;
+        }
+      );
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.dateRange = [];
+      this.resetForm("queryForm");
+      this.queryParams.pageNum = 1;
+      this.$refs.tables.sort(this.defaultSort.prop, this.defaultSort.order)
+    },
+    /** 澶氶�夋閫変腑鏁版嵁 */
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.infoId)
+      this.single = selection.length!=1
+      this.multiple = !selection.length
+      this.selectName = selection.map(item => item.userName);
+    },
+    /** 鎺掑簭瑙﹀彂浜嬩欢 */
+    handleSortChange(column, prop, order) {
+      this.queryParams.orderByColumn = column.prop;
+      this.queryParams.isAsc = column.order;
+      this.getList();
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const infoIds = row.infoId || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎璁块棶缂栧彿涓�"' + infoIds + '"鐨勬暟鎹」锛�').then(function() {
+        return delLogininfor(infoIds);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 娓呯┖鎸夐挳鎿嶄綔 */
+    handleClean() {
+      this.$modal.confirm('鏄惁纭娓呯┖鎵�鏈夌櫥褰曟棩蹇楁暟鎹」锛�').then(function() {
+        return cleanLogininfor();
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("娓呯┖鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 瑙i攣鎸夐挳鎿嶄綔 */
+    handleUnlock() {
+      const username = this.selectName;
+      this.$modal.confirm('鏄惁纭瑙i攣鐢ㄦ埛"' + username + '"鏁版嵁椤�?').then(function() {
+        return unlockLogininfor(username);
+      }).then(() => {
+        this.$modal.msgSuccess("鐢ㄦ埛" + username + "瑙i攣鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('monitor/logininfor/export', {
+        ...this.queryParams
+      }, `logininfor_${new Date().getTime()}.xlsx`)
+    }
+  }
+};
+</script>
+
diff --git a/jcdm-ui/src/views/monitor/online/index.vue b/jcdm-ui/src/views/monitor/online/index.vue
new file mode 100644
index 0000000..ad613c9
--- /dev/null
+++ b/jcdm-ui/src/views/monitor/online/index.vue
@@ -0,0 +1,122 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" label-width="68px">
+      <el-form-item label="鐧诲綍鍦板潃" prop="ipaddr">
+        <el-input
+          v-model="queryParams.ipaddr"
+          placeholder="璇疯緭鍏ョ櫥褰曞湴鍧�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="鐢ㄦ埛鍚嶇О" prop="userName">
+        <el-input
+          v-model="queryParams.userName"
+          placeholder="璇疯緭鍏ョ敤鎴峰悕绉�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+
+    </el-form>
+    <el-table
+      v-loading="loading"
+      :data="list.slice((pageNum-1)*pageSize,pageNum*pageSize)"
+      style="width: 100%;"
+    >
+      <el-table-column label="搴忓彿" type="index" align="center">
+        <template slot-scope="scope">
+          <span>{{(pageNum - 1) * pageSize + scope.$index + 1}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="浼氳瘽缂栧彿" align="center" prop="tokenId" :show-overflow-tooltip="true" />
+      <el-table-column label="鐧诲綍鍚嶇О" align="center" prop="userName" :show-overflow-tooltip="true" />
+      <el-table-column label="閮ㄩ棬鍚嶇О" align="center" prop="deptName" />
+      <el-table-column label="涓绘満" align="center" prop="ipaddr" :show-overflow-tooltip="true" />
+      <el-table-column label="鐧诲綍鍦扮偣" align="center" prop="loginLocation" :show-overflow-tooltip="true" />
+      <el-table-column label="娴忚鍣�" align="center" prop="browser" />
+      <el-table-column label="鎿嶄綔绯荤粺" align="center" prop="os" />
+      <el-table-column label="鐧诲綍鏃堕棿" align="center" prop="loginTime" width="180">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.loginTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleForceLogout(scope.row)"
+            v-hasPermi="['monitor:online:forceLogout']"
+          >寮洪��</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination v-show="total>0" :total="total" :page.sync="pageNum" :limit.sync="pageSize" />
+  </div>
+</template>
+
+<script>
+import { list, forceLogout } from "@/api/monitor/online";
+
+export default {
+  name: "Online",
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 琛ㄦ牸鏁版嵁
+      list: [],
+      pageNum: 1,
+      pageSize: 10,
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        ipaddr: undefined,
+        userName: undefined
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 鏌ヨ鐧诲綍鏃ュ織鍒楄〃 */
+    getList() {
+      this.loading = true;
+      list(this.queryParams).then(response => {
+        this.list = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    /** 寮洪��鎸夐挳鎿嶄綔 */
+    handleForceLogout(row) {
+      this.$modal.confirm('鏄惁纭寮洪��鍚嶇О涓�"' + row.userName + '"鐨勭敤鎴凤紵').then(function() {
+        return forceLogout(row.tokenId);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("寮洪��鎴愬姛");
+      }).catch(() => {});
+    }
+  }
+};
+</script>
+
diff --git a/jcdm-ui/src/views/monitor/operlog/index.vue b/jcdm-ui/src/views/monitor/operlog/index.vue
new file mode 100644
index 0000000..4a1828f
--- /dev/null
+++ b/jcdm-ui/src/views/monitor/operlog/index.vue
@@ -0,0 +1,323 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="鎿嶄綔鍦板潃" prop="operIp">
+        <el-input
+          v-model="queryParams.operIp"
+          placeholder="璇疯緭鍏ユ搷浣滃湴鍧�"
+          clearable
+          style="width: 240px;"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="绯荤粺妯″潡" prop="title">
+        <el-input
+          v-model="queryParams.title"
+          placeholder="璇疯緭鍏ョ郴缁熸ā鍧�"
+          clearable
+          style="width: 240px;"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="鎿嶄綔浜哄憳" prop="operName">
+        <el-input
+          v-model="queryParams.operName"
+          placeholder="璇疯緭鍏ユ搷浣滀汉鍛�"
+          clearable
+          style="width: 240px;"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="绫诲瀷" prop="businessType">
+        <el-select
+          v-model="queryParams.businessType"
+          placeholder="鎿嶄綔绫诲瀷"
+          clearable
+          style="width: 240px"
+        >
+          <el-option
+            v-for="dict in dict.type.sys_oper_type"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="鐘舵��" prop="status">
+        <el-select
+          v-model="queryParams.status"
+          placeholder="鎿嶄綔鐘舵��"
+          clearable
+          style="width: 240px"
+        >
+          <el-option
+            v-for="dict in dict.type.sys_common_status"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="鎿嶄綔鏃堕棿">
+        <el-date-picker
+          v-model="dateRange"
+          style="width: 240px"
+          value-format="yyyy-MM-dd HH:mm:ss"
+          type="daterange"
+          range-separator="-"
+          start-placeholder="寮�濮嬫棩鏈�"
+          end-placeholder="缁撴潫鏃ユ湡"
+          :default-time="['00:00:00', '23:59:59']"
+        ></el-date-picker>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['monitor:operlog:remove']"
+        >鍒犻櫎</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          @click="handleClean"
+          v-hasPermi="['monitor:operlog:remove']"
+        >娓呯┖</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['monitor:operlog:export']"
+        >瀵煎嚭</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table ref="tables" v-loading="loading" :data="list" @selection-change="handleSelectionChange" :default-sort="defaultSort" @sort-change="handleSortChange">
+      <el-table-column type="selection" width="50" align="center" />
+      <el-table-column label="鏃ュ織缂栧彿" align="center" prop="operId" />
+      <el-table-column label="绯荤粺妯″潡" align="center" prop="title" :show-overflow-tooltip="true" />
+      <el-table-column label="鎿嶄綔绫诲瀷" align="center" prop="businessType">
+        <template slot-scope="scope">
+          <dict-tag :options="dict.type.sys_oper_type" :value="scope.row.businessType"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="鎿嶄綔浜哄憳" align="center" prop="operName" width="110" :show-overflow-tooltip="true" sortable="custom" :sort-orders="['descending', 'ascending']" />
+      <el-table-column label="鎿嶄綔鍦板潃" align="center" prop="operIp" width="130" :show-overflow-tooltip="true" />
+      <el-table-column label="鎿嶄綔鍦扮偣" align="center" prop="operLocation" :show-overflow-tooltip="true" />
+      <el-table-column label="鎿嶄綔鐘舵��" align="center" prop="status">
+        <template slot-scope="scope">
+          <dict-tag :options="dict.type.sys_common_status" :value="scope.row.status"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="鎿嶄綔鏃ユ湡" align="center" prop="operTime" width="160" sortable="custom" :sort-orders="['descending', 'ascending']">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.operTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="娑堣�楁椂闂�" align="center" prop="costTime" width="110" :show-overflow-tooltip="true" sortable="custom" :sort-orders="['descending', 'ascending']">
+        <template slot-scope="scope">
+          <span>{{ scope.row.costTime }}姣</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-view"
+            @click="handleView(scope.row,scope.index)"
+            v-hasPermi="['monitor:operlog:query']"
+          >璇︾粏</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 鎿嶄綔鏃ュ織璇︾粏 -->
+    <el-dialog title="鎿嶄綔鏃ュ織璇︾粏" :visible.sync="open" width="800px" append-to-body>
+      <el-form ref="form" :model="form" label-width="100px" size="mini">
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="鎿嶄綔妯″潡锛�">{{ form.title }} / {{ typeFormat(form) }}</el-form-item>
+            <el-form-item
+              label="鐧诲綍淇℃伅锛�"
+            >{{ form.operName }} / {{ form.operIp }} / {{ form.operLocation }}</el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="璇锋眰鍦板潃锛�">{{ form.operUrl }}</el-form-item>
+            <el-form-item label="璇锋眰鏂瑰紡锛�">{{ form.requestMethod }}</el-form-item>
+          </el-col>
+          <el-col :span="24">
+            <el-form-item label="鎿嶄綔鏂规硶锛�">{{ form.method }}</el-form-item>
+          </el-col>
+          <el-col :span="24">
+            <el-form-item label="璇锋眰鍙傛暟锛�">{{ form.operParam }}</el-form-item>
+          </el-col>
+          <el-col :span="24">
+            <el-form-item label="杩斿洖鍙傛暟锛�">{{ form.jsonResult }}</el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="鎿嶄綔鐘舵�侊細">
+              <div v-if="form.status === 0">姝e父</div>
+              <div v-else-if="form.status === 1">澶辫触</div>
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="娑堣�楁椂闂达細">{{ form.costTime }}姣</el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="鎿嶄綔鏃堕棿锛�">{{ parseTime(form.operTime) }}</el-form-item>
+          </el-col>
+          <el-col :span="24">
+            <el-form-item label="寮傚父淇℃伅锛�" v-if="form.status === 1">{{ form.errorMsg }}</el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="open = false">鍏� 闂�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { list, delOperlog, cleanOperlog } from "@/api/monitor/operlog";
+
+export default {
+  name: "Operlog",
+  dicts: ['sys_oper_type', 'sys_common_status'],
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 琛ㄦ牸鏁版嵁
+      list: [],
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏃ユ湡鑼冨洿
+      dateRange: [],
+      // 榛樿鎺掑簭
+      defaultSort: {prop: 'operTime', order: 'descending'},
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        operIp: undefined,
+        title: undefined,
+        operName: undefined,
+        businessType: undefined,
+        status: undefined
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 鏌ヨ鐧诲綍鏃ュ織 */
+    getList() {
+      this.loading = true;
+      list(this.addDateRange(this.queryParams, this.dateRange)).then( response => {
+          this.list = response.rows;
+          this.total = response.total;
+          this.loading = false;
+        }
+      );
+    },
+    // 鎿嶄綔鏃ュ織绫诲瀷瀛楀吀缈昏瘧
+    typeFormat(row, column) {
+      return this.selectDictLabel(this.dict.type.sys_oper_type, row.businessType);
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.dateRange = [];
+      this.resetForm("queryForm");
+      this.queryParams.pageNum = 1;
+      this.$refs.tables.sort(this.defaultSort.prop, this.defaultSort.order)
+    },
+    /** 澶氶�夋閫変腑鏁版嵁 */
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.operId)
+      this.multiple = !selection.length
+    },
+    /** 鎺掑簭瑙﹀彂浜嬩欢 */
+    handleSortChange(column, prop, order) {
+      this.queryParams.orderByColumn = column.prop;
+      this.queryParams.isAsc = column.order;
+      this.getList();
+    },
+    /** 璇︾粏鎸夐挳鎿嶄綔 */
+    handleView(row) {
+      this.open = true;
+      this.form = row;
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const operIds = row.operId || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎鏃ュ織缂栧彿涓�"' + operIds + '"鐨勬暟鎹」锛�').then(function() {
+        return delOperlog(operIds);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 娓呯┖鎸夐挳鎿嶄綔 */
+    handleClean() {
+      this.$modal.confirm('鏄惁纭娓呯┖鎵�鏈夋搷浣滄棩蹇楁暟鎹」锛�').then(function() {
+        return cleanOperlog();
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("娓呯┖鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('monitor/operlog/export', {
+        ...this.queryParams
+      }, `operlog_${new Date().getTime()}.xlsx`)
+    }
+  }
+};
+</script>
+
diff --git a/jcdm-ui/src/views/monitor/server/index.vue b/jcdm-ui/src/views/monitor/server/index.vue
new file mode 100644
index 0000000..15ffc9a
--- /dev/null
+++ b/jcdm-ui/src/views/monitor/server/index.vue
@@ -0,0 +1,207 @@
+<template>
+  <div class="app-container">
+    <el-row>
+      <el-col :span="12" class="card-box">
+        <el-card>
+          <div slot="header"><span><i class="el-icon-cpu"></i> CPU</span></div>
+          <div class="el-table el-table--enable-row-hover el-table--medium">
+            <table cellspacing="0" style="width: 100%;">
+              <thead>
+                <tr>
+                  <th class="el-table__cell is-leaf"><div class="cell">灞炴��</div></th>
+                  <th class="el-table__cell is-leaf"><div class="cell">鍊�</div></th>
+                </tr>
+              </thead>
+              <tbody>
+                <tr>
+                  <td class="el-table__cell is-leaf"><div class="cell">鏍稿績鏁�</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.cpu">{{ server.cpu.cpuNum }}</div></td>
+                </tr>
+                <tr>
+                  <td class="el-table__cell is-leaf"><div class="cell">鐢ㄦ埛浣跨敤鐜�</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.cpu">{{ server.cpu.used }}%</div></td>
+                </tr>
+                <tr>
+                  <td class="el-table__cell is-leaf"><div class="cell">绯荤粺浣跨敤鐜�</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.cpu">{{ server.cpu.sys }}%</div></td>
+                </tr>
+                <tr>
+                  <td class="el-table__cell is-leaf"><div class="cell">褰撳墠绌洪棽鐜�</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.cpu">{{ server.cpu.free }}%</div></td>
+                </tr>
+              </tbody>
+            </table>
+          </div>
+        </el-card>
+      </el-col>
+
+      <el-col :span="12" class="card-box">
+        <el-card>
+          <div slot="header"><span><i class="el-icon-tickets"></i> 鍐呭瓨</span></div>
+          <div class="el-table el-table--enable-row-hover el-table--medium">
+            <table cellspacing="0" style="width: 100%;">
+              <thead>
+                <tr>
+                  <th class="el-table__cell is-leaf"><div class="cell">灞炴��</div></th>
+                  <th class="el-table__cell is-leaf"><div class="cell">鍐呭瓨</div></th>
+                  <th class="el-table__cell is-leaf"><div class="cell">JVM</div></th>
+                </tr>
+              </thead>
+              <tbody>
+                <tr>
+                  <td class="el-table__cell is-leaf"><div class="cell">鎬诲唴瀛�</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.mem">{{ server.mem.total }}G</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.total }}M</div></td>
+                </tr>
+                <tr>
+                  <td class="el-table__cell is-leaf"><div class="cell">宸茬敤鍐呭瓨</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.mem">{{ server.mem.used}}G</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.used}}M</div></td>
+                </tr>
+                <tr>
+                  <td class="el-table__cell is-leaf"><div class="cell">鍓╀綑鍐呭瓨</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.mem">{{ server.mem.free }}G</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.free }}M</div></td>
+                </tr>
+                <tr>
+                  <td class="el-table__cell is-leaf"><div class="cell">浣跨敤鐜�</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.mem" :class="{'text-danger': server.mem.usage > 80}">{{ server.mem.usage }}%</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm" :class="{'text-danger': server.jvm.usage > 80}">{{ server.jvm.usage }}%</div></td>
+                </tr>
+              </tbody>
+            </table>
+          </div>
+        </el-card>
+      </el-col>
+
+      <el-col :span="24" class="card-box">
+        <el-card>
+          <div slot="header">
+            <span><i class="el-icon-monitor"></i> 鏈嶅姟鍣ㄤ俊鎭�</span>
+          </div>
+          <div class="el-table el-table--enable-row-hover el-table--medium">
+            <table cellspacing="0" style="width: 100%;">
+              <tbody>
+                <tr>
+                  <td class="el-table__cell is-leaf"><div class="cell">鏈嶅姟鍣ㄥ悕绉�</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.sys">{{ server.sys.computerName }}</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell">鎿嶄綔绯荤粺</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.sys">{{ server.sys.osName }}</div></td>
+                </tr>
+                <tr>
+                  <td class="el-table__cell is-leaf"><div class="cell">鏈嶅姟鍣↖P</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.sys">{{ server.sys.computerIp }}</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell">绯荤粺鏋舵瀯</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.sys">{{ server.sys.osArch }}</div></td>
+                </tr>
+              </tbody>
+            </table>
+          </div>
+        </el-card>
+      </el-col>
+
+      <el-col :span="24" class="card-box">
+        <el-card>
+          <div slot="header">
+            <span><i class="el-icon-coffee-cup"></i> Java铏氭嫙鏈轰俊鎭�</span>
+          </div>
+          <div class="el-table el-table--enable-row-hover el-table--medium">
+            <table cellspacing="0" style="width: 100%;table-layout:fixed;">
+              <tbody>
+                <tr>
+                  <td class="el-table__cell is-leaf"><div class="cell">Java鍚嶇О</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.name }}</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell">Java鐗堟湰</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.version }}</div></td>
+                </tr>
+                <tr>
+                  <td class="el-table__cell is-leaf"><div class="cell">鍚姩鏃堕棿</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.startTime }}</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell">杩愯鏃堕暱</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.runTime }}</div></td>
+                </tr>
+                <tr>
+                  <td colspan="1" class="el-table__cell is-leaf"><div class="cell">瀹夎璺緞</div></td>
+                  <td colspan="3" class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.home }}</div></td>
+                </tr>
+                <tr>
+                  <td colspan="1" class="el-table__cell is-leaf"><div class="cell">椤圭洰璺緞</div></td>
+                  <td colspan="3" class="el-table__cell is-leaf"><div class="cell" v-if="server.sys">{{ server.sys.userDir }}</div></td>
+                </tr>
+                <tr>
+                  <td colspan="1" class="el-table__cell is-leaf"><div class="cell">杩愯鍙傛暟</div></td>
+                  <td colspan="3" class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.inputArgs }}</div></td>
+                </tr>
+              </tbody>
+            </table>
+          </div>
+        </el-card>
+      </el-col>
+
+      <el-col :span="24" class="card-box">
+        <el-card>
+          <div slot="header">
+            <span><i class="el-icon-receiving"></i> 纾佺洏鐘舵��</span>
+          </div>
+          <div class="el-table el-table--enable-row-hover el-table--medium">
+            <table cellspacing="0" style="width: 100%;">
+              <thead>
+                <tr>
+                  <th class="el-table__cell el-table__cell is-leaf"><div class="cell">鐩樼璺緞</div></th>
+                  <th class="el-table__cell is-leaf"><div class="cell">鏂囦欢绯荤粺</div></th>
+                  <th class="el-table__cell is-leaf"><div class="cell">鐩樼绫诲瀷</div></th>
+                  <th class="el-table__cell is-leaf"><div class="cell">鎬诲ぇ灏�</div></th>
+                  <th class="el-table__cell is-leaf"><div class="cell">鍙敤澶у皬</div></th>
+                  <th class="el-table__cell is-leaf"><div class="cell">宸茬敤澶у皬</div></th>
+                  <th class="el-table__cell is-leaf"><div class="cell">宸茬敤鐧惧垎姣�</div></th>
+                </tr>
+              </thead>
+              <tbody v-if="server.sysFiles">
+                <tr v-for="(sysFile, index) in server.sysFiles" :key="index">
+                  <td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.dirName }}</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.sysTypeName }}</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.typeName }}</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.total }}</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.free }}</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.used }}</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell" :class="{'text-danger': sysFile.usage > 80}">{{ sysFile.usage }}%</div></td>
+                </tr>
+              </tbody>
+            </table>
+          </div>
+        </el-card>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import { getServer } from "@/api/monitor/server";
+
+export default {
+  name: "Server",
+  data() {
+    return {
+      // 鏈嶅姟鍣ㄤ俊鎭�
+      server: []
+    };
+  },
+  created() {
+    this.getList();
+    this.openLoading();
+  },
+  methods: {
+    /** 鏌ヨ鏈嶅姟鍣ㄤ俊鎭� */
+    getList() {
+      getServer().then(response => {
+        this.server = response.data;
+        this.$modal.closeLoading();
+      });
+    },
+    // 鎵撳紑鍔犺浇灞�
+    openLoading() {
+      this.$modal.loading("姝e湪鍔犺浇鏈嶅姟鐩戞帶鏁版嵁锛岃绋嶅�欙紒");
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/redirect.vue b/jcdm-ui/src/views/redirect.vue
new file mode 100644
index 0000000..db4c1d6
--- /dev/null
+++ b/jcdm-ui/src/views/redirect.vue
@@ -0,0 +1,12 @@
+<script>
+export default {
+  created() {
+    const { params, query } = this.$route
+    const { path } = params
+    this.$router.replace({ path: '/' + path, query })
+  },
+  render: function(h) {
+    return h() // avoid warning message
+  }
+}
+</script>
diff --git a/jcdm-ui/src/views/register.vue b/jcdm-ui/src/views/register.vue
new file mode 100644
index 0000000..dfde80d
--- /dev/null
+++ b/jcdm-ui/src/views/register.vue
@@ -0,0 +1,209 @@
+<template>
+  <div class="register">
+    <el-form ref="registerForm" :model="registerForm" :rules="registerRules" class="register-form">
+      <h3 class="title">姹熷MES绠$悊绯荤粺</h3>
+      <el-form-item prop="username">
+        <el-input v-model="registerForm.username" type="text" auto-complete="off" placeholder="璐﹀彿">
+          <svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon" />
+        </el-input>
+      </el-form-item>
+      <el-form-item prop="password">
+        <el-input
+          v-model="registerForm.password"
+          type="password"
+          auto-complete="off"
+          placeholder="瀵嗙爜"
+          @keyup.enter.native="handleRegister"
+        >
+          <svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon" />
+        </el-input>
+      </el-form-item>
+      <el-form-item prop="confirmPassword">
+        <el-input
+          v-model="registerForm.confirmPassword"
+          type="password"
+          auto-complete="off"
+          placeholder="纭瀵嗙爜"
+          @keyup.enter.native="handleRegister"
+        >
+          <svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon" />
+        </el-input>
+      </el-form-item>
+      <el-form-item prop="code" v-if="captchaEnabled">
+        <el-input
+          v-model="registerForm.code"
+          auto-complete="off"
+          placeholder="楠岃瘉鐮�"
+          style="width: 63%"
+          @keyup.enter.native="handleRegister"
+        >
+          <svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon" />
+        </el-input>
+        <div class="register-code">
+          <img :src="codeUrl" @click="getCode" class="register-code-img"/>
+        </div>
+      </el-form-item>
+      <el-form-item style="width:100%;">
+        <el-button
+          :loading="loading"
+          size="medium"
+          type="primary"
+          style="width:100%;"
+          @click.native.prevent="handleRegister"
+        >
+          <span v-if="!loading">娉� 鍐�</span>
+          <span v-else>娉� 鍐� 涓�...</span>
+        </el-button>
+        <div style="float: right;">
+          <router-link class="link-type" :to="'/login'">浣跨敤宸叉湁璐︽埛鐧诲綍</router-link>
+        </div>
+      </el-form-item>
+    </el-form>
+    <!--  搴曢儴  -->
+    <div class="el-register-footer">
+      <span>Copyright 漏 2018-2023 jcdm.vip All Rights Reserved.</span>
+    </div>
+  </div>
+</template>
+
+<script>
+import { getCodeImg, register } from "@/api/login";
+
+export default {
+  name: "Register",
+  data() {
+    const equalToPassword = (rule, value, callback) => {
+      if (this.registerForm.password !== value) {
+        callback(new Error("涓ゆ杈撳叆鐨勫瘑鐮佷笉涓�鑷�"));
+      } else {
+        callback();
+      }
+    };
+    return {
+      codeUrl: "",
+      registerForm: {
+        username: "",
+        password: "",
+        confirmPassword: "",
+        code: "",
+        uuid: ""
+      },
+      registerRules: {
+        username: [
+          { required: true, trigger: "blur", message: "璇疯緭鍏ユ偍鐨勮处鍙�" },
+          { min: 2, max: 20, message: '鐢ㄦ埛璐﹀彿闀垮害蹇呴』浠嬩簬 2 鍜� 20 涔嬮棿', trigger: 'blur' }
+        ],
+        password: [
+          { required: true, trigger: "blur", message: "璇疯緭鍏ユ偍鐨勫瘑鐮�" },
+          { min: 5, max: 20, message: '鐢ㄦ埛瀵嗙爜闀垮害蹇呴』浠嬩簬 5 鍜� 20 涔嬮棿', trigger: 'blur' }
+        ],
+        confirmPassword: [
+          { required: true, trigger: "blur", message: "璇峰啀娆¤緭鍏ユ偍鐨勫瘑鐮�" },
+          { required: true, validator: equalToPassword, trigger: "blur" }
+        ],
+        code: [{ required: true, trigger: "change", message: "璇疯緭鍏ラ獙璇佺爜" }]
+      },
+      loading: false,
+      captchaEnabled: true
+    };
+  },
+  created() {
+    this.getCode();
+  },
+  methods: {
+    getCode() {
+      getCodeImg().then(res => {
+        this.captchaEnabled = res.captchaEnabled === undefined ? true : res.captchaEnabled;
+        if (this.captchaEnabled) {
+          this.codeUrl = "data:image/gif;base64," + res.img;
+          this.registerForm.uuid = res.uuid;
+        }
+      });
+    },
+    handleRegister() {
+      this.$refs.registerForm.validate(valid => {
+        if (valid) {
+          this.loading = true;
+          register(this.registerForm).then(res => {
+            const username = this.registerForm.username;
+            this.$alert("<font color='red'>鎭枩浣狅紝鎮ㄧ殑璐﹀彿 " + username + " 娉ㄥ唽鎴愬姛锛�</font>", '绯荤粺鎻愮ず', {
+              dangerouslyUseHTMLString: true,
+              type: 'success'
+            }).then(() => {
+              this.$router.push("/login");
+            }).catch(() => {});
+          }).catch(() => {
+            this.loading = false;
+            if (this.captchaEnabled) {
+              this.getCode();
+            }
+          })
+        }
+      });
+    }
+  }
+};
+</script>
+
+<style rel="stylesheet/scss" lang="scss">
+.register {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  height: 100%;
+  background-image: url("../assets/images/login-background.jpg");
+  background-size: cover;
+}
+.title {
+  margin: 0px auto 30px auto;
+  text-align: center;
+  color: #707070;
+}
+
+.register-form {
+  border-radius: 6px;
+  background: #ffffff;
+  width: 400px;
+  padding: 25px 25px 5px 25px;
+  .el-input {
+    height: 38px;
+    input {
+      height: 38px;
+    }
+  }
+  .input-icon {
+    height: 39px;
+    width: 14px;
+    margin-left: 2px;
+  }
+}
+.register-tip {
+  font-size: 13px;
+  text-align: center;
+  color: #bfbfbf;
+}
+.register-code {
+  width: 33%;
+  height: 38px;
+  float: right;
+  img {
+    cursor: pointer;
+    vertical-align: middle;
+  }
+}
+.el-register-footer {
+  height: 40px;
+  line-height: 40px;
+  position: fixed;
+  bottom: 0;
+  width: 100%;
+  text-align: center;
+  color: #fff;
+  font-family: Arial;
+  font-size: 12px;
+  letter-spacing: 1px;
+}
+.register-code-img {
+  height: 38px;
+}
+</style>
diff --git a/jcdm-ui/src/views/system/config/index.vue b/jcdm-ui/src/views/system/config/index.vue
new file mode 100644
index 0000000..3ab81fc
--- /dev/null
+++ b/jcdm-ui/src/views/system/config/index.vue
@@ -0,0 +1,343 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="鍙傛暟鍚嶇О" prop="configName">
+        <el-input
+          v-model="queryParams.configName"
+          placeholder="璇疯緭鍏ュ弬鏁板悕绉�"
+          clearable
+          style="width: 240px"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="鍙傛暟閿悕" prop="configKey">
+        <el-input
+          v-model="queryParams.configKey"
+          placeholder="璇疯緭鍏ュ弬鏁伴敭鍚�"
+          clearable
+          style="width: 240px"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="绯荤粺鍐呯疆" prop="configType">
+        <el-select v-model="queryParams.configType" placeholder="绯荤粺鍐呯疆" clearable>
+          <el-option
+            v-for="dict in dict.type.sys_yes_no"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="鍒涘缓鏃堕棿">
+        <el-date-picker
+          v-model="dateRange"
+          style="width: 240px"
+          value-format="yyyy-MM-dd"
+          type="daterange"
+          range-separator="-"
+          start-placeholder="寮�濮嬫棩鏈�"
+          end-placeholder="缁撴潫鏃ユ湡"
+        ></el-date-picker>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['system:config:add']"
+        >鏂板</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['system:config:edit']"
+        >淇敼</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['system:config:remove']"
+        >鍒犻櫎</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['system:config:export']"
+        >瀵煎嚭</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-refresh"
+          size="mini"
+          @click="handleRefreshCache"
+          v-hasPermi="['system:config:remove']"
+        >鍒锋柊缂撳瓨</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="configList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="鍙傛暟涓婚敭" align="center" prop="configId" />
+      <el-table-column label="鍙傛暟鍚嶇О" align="center" prop="configName" :show-overflow-tooltip="true" />
+      <el-table-column label="鍙傛暟閿悕" align="center" prop="configKey" :show-overflow-tooltip="true" />
+      <el-table-column label="鍙傛暟閿��" align="center" prop="configValue" :show-overflow-tooltip="true" />
+      <el-table-column label="绯荤粺鍐呯疆" align="center" prop="configType">
+        <template slot-scope="scope">
+          <dict-tag :options="dict.type.sys_yes_no" :value="scope.row.configType"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="澶囨敞" align="center" prop="remark" :show-overflow-tooltip="true" />
+      <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['system:config:edit']"
+          >淇敼</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['system:config:remove']"
+          >鍒犻櫎</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 娣诲姞鎴栦慨鏀瑰弬鏁伴厤缃璇濇 -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="鍙傛暟鍚嶇О" prop="configName">
+          <el-input v-model="form.configName" placeholder="璇疯緭鍏ュ弬鏁板悕绉�" />
+        </el-form-item>
+        <el-form-item label="鍙傛暟閿悕" prop="configKey">
+          <el-input v-model="form.configKey" placeholder="璇疯緭鍏ュ弬鏁伴敭鍚�" />
+        </el-form-item>
+        <el-form-item label="鍙傛暟閿��" prop="configValue">
+          <el-input v-model="form.configValue" placeholder="璇疯緭鍏ュ弬鏁伴敭鍊�" />
+        </el-form-item>
+        <el-form-item label="绯荤粺鍐呯疆" prop="configType">
+          <el-radio-group v-model="form.configType">
+            <el-radio
+              v-for="dict in dict.type.sys_yes_no"
+              :key="dict.value"
+              :label="dict.value"
+            >{{dict.label}}</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="澶囨敞" prop="remark">
+          <el-input v-model="form.remark" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listConfig, getConfig, delConfig, addConfig, updateConfig, refreshCache } from "@/api/system/config";
+
+export default {
+  name: "Config",
+  dicts: ['sys_yes_no'],
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 鍙傛暟琛ㄦ牸鏁版嵁
+      configList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏃ユ湡鑼冨洿
+      dateRange: [],
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        configName: undefined,
+        configKey: undefined,
+        configType: undefined
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        configName: [
+          { required: true, message: "鍙傛暟鍚嶇О涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        configKey: [
+          { required: true, message: "鍙傛暟閿悕涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        configValue: [
+          { required: true, message: "鍙傛暟閿�间笉鑳戒负绌�", trigger: "blur" }
+        ]
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 鏌ヨ鍙傛暟鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listConfig(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
+          this.configList = response.rows;
+          this.total = response.total;
+          this.loading = false;
+        }
+      );
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        configId: undefined,
+        configName: undefined,
+        configKey: undefined,
+        configValue: undefined,
+        configType: "Y",
+        remark: undefined
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.dateRange = [];
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "娣诲姞鍙傛暟";
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.configId)
+      this.single = selection.length!=1
+      this.multiple = !selection.length
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.reset();
+      const configId = row.configId || this.ids
+      getConfig(configId).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "淇敼鍙傛暟";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm: function() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.configId != undefined) {
+            updateConfig(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addConfig(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const configIds = row.configId || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎鍙傛暟缂栧彿涓�"' + configIds + '"鐨勬暟鎹」锛�').then(function() {
+          return delConfig(configIds);
+        }).then(() => {
+          this.getList();
+          this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+        }).catch(() => {});
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('system/config/export', {
+        ...this.queryParams
+      }, `config_${new Date().getTime()}.xlsx`)
+    },
+    /** 鍒锋柊缂撳瓨鎸夐挳鎿嶄綔 */
+    handleRefreshCache() {
+      refreshCache().then(() => {
+        this.$modal.msgSuccess("鍒锋柊鎴愬姛");
+      });
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/system/dept/index.vue b/jcdm-ui/src/views/system/dept/index.vue
new file mode 100644
index 0000000..e502b4e
--- /dev/null
+++ b/jcdm-ui/src/views/system/dept/index.vue
@@ -0,0 +1,340 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch">
+      <el-form-item label="閮ㄩ棬鍚嶇О" prop="deptName">
+        <el-input
+          v-model="queryParams.deptName"
+          placeholder="璇疯緭鍏ラ儴闂ㄥ悕绉�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="鐘舵��" prop="status">
+        <el-select v-model="queryParams.status" placeholder="閮ㄩ棬鐘舵��" clearable>
+          <el-option
+            v-for="dict in dict.type.sys_normal_disable"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['system:dept:add']"
+        >鏂板</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="info"
+          plain
+          icon="el-icon-sort"
+          size="mini"
+          @click="toggleExpandAll"
+        >灞曞紑/鎶樺彔</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table
+      v-if="refreshTable"
+      v-loading="loading"
+      :data="deptList"
+      row-key="deptId"
+      :default-expand-all="isExpandAll"
+      :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
+    >
+      <el-table-column prop="deptName" label="閮ㄩ棬鍚嶇О" width="260"></el-table-column>
+      <el-table-column prop="orderNum" label="鎺掑簭" width="200"></el-table-column>
+      <el-table-column prop="status" label="鐘舵��" width="100">
+        <template slot-scope="scope">
+          <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="200">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['system:dept:edit']"
+          >淇敼</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-plus"
+            @click="handleAdd(scope.row)"
+            v-hasPermi="['system:dept:add']"
+          >鏂板</el-button>
+          <el-button
+            v-if="scope.row.parentId != 0"
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['system:dept:remove']"
+          >鍒犻櫎</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- 娣诲姞鎴栦慨鏀归儴闂ㄥ璇濇 -->
+    <el-dialog :title="title" :visible.sync="open" width="600px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-row>
+          <el-col :span="24" v-if="form.parentId !== 0">
+            <el-form-item label="涓婄骇閮ㄩ棬" prop="parentId">
+              <treeselect v-model="form.parentId" :options="deptOptions" :normalizer="normalizer" placeholder="閫夋嫨涓婄骇閮ㄩ棬" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="閮ㄩ棬鍚嶇О" prop="deptName">
+              <el-input v-model="form.deptName" placeholder="璇疯緭鍏ラ儴闂ㄥ悕绉�" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鏄剧ず鎺掑簭" prop="orderNum">
+              <el-input-number v-model="form.orderNum" controls-position="right" :min="0" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="璐熻矗浜�" prop="leader">
+              <el-input v-model="form.leader" placeholder="璇疯緭鍏ヨ礋璐d汉" maxlength="20" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鑱旂郴鐢佃瘽" prop="phone">
+              <el-input v-model="form.phone" placeholder="璇疯緭鍏ヨ仈绯荤數璇�" maxlength="11" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="閭" prop="email">
+              <el-input v-model="form.email" placeholder="璇疯緭鍏ラ偖绠�" maxlength="50" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="閮ㄩ棬鐘舵��">
+              <el-radio-group v-model="form.status">
+                <el-radio
+                  v-for="dict in dict.type.sys_normal_disable"
+                  :key="dict.value"
+                  :label="dict.value"
+                >{{dict.label}}</el-radio>
+              </el-radio-group>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listDept, getDept, delDept, addDept, updateDept, listDeptExcludeChild } from "@/api/system/dept";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+
+export default {
+  name: "Dept",
+  dicts: ['sys_normal_disable'],
+  components: { Treeselect },
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 琛ㄦ牸鏍戞暟鎹�
+      deptList: [],
+      // 閮ㄩ棬鏍戦�夐」
+      deptOptions: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏄惁灞曞紑锛岄粯璁ゅ叏閮ㄥ睍寮�
+      isExpandAll: true,
+      // 閲嶆柊娓叉煋琛ㄦ牸鐘舵��
+      refreshTable: true,
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        deptName: undefined,
+        status: undefined
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        parentId: [
+          { required: true, message: "涓婄骇閮ㄩ棬涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        deptName: [
+          { required: true, message: "閮ㄩ棬鍚嶇О涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        orderNum: [
+          { required: true, message: "鏄剧ず鎺掑簭涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        email: [
+          {
+            type: "email",
+            message: "璇疯緭鍏ユ纭殑閭鍦板潃",
+            trigger: ["blur", "change"]
+          }
+        ],
+        phone: [
+          {
+            pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
+            message: "璇疯緭鍏ユ纭殑鎵嬫満鍙风爜",
+            trigger: "blur"
+          }
+        ]
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 鏌ヨ閮ㄩ棬鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listDept(this.queryParams).then(response => {
+        this.deptList = this.handleTree(response.data, "deptId");
+        this.loading = false;
+      });
+    },
+    /** 杞崲閮ㄩ棬鏁版嵁缁撴瀯 */
+    normalizer(node) {
+      if (node.children && !node.children.length) {
+        delete node.children;
+      }
+      return {
+        id: node.deptId,
+        label: node.deptName,
+        children: node.children
+      };
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        deptId: undefined,
+        parentId: undefined,
+        deptName: undefined,
+        orderNum: undefined,
+        leader: undefined,
+        phone: undefined,
+        email: undefined,
+        status: "0"
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd(row) {
+      this.reset();
+      if (row != undefined) {
+        this.form.parentId = row.deptId;
+      }
+      this.open = true;
+      this.title = "娣诲姞閮ㄩ棬";
+      listDept().then(response => {
+        this.deptOptions = this.handleTree(response.data, "deptId");
+      });
+    },
+    /** 灞曞紑/鎶樺彔鎿嶄綔 */
+    toggleExpandAll() {
+      this.refreshTable = false;
+      this.isExpandAll = !this.isExpandAll;
+      this.$nextTick(() => {
+        this.refreshTable = true;
+      });
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.reset();
+      getDept(row.deptId).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "淇敼閮ㄩ棬";
+        listDeptExcludeChild(row.deptId).then(response => {
+          this.deptOptions = this.handleTree(response.data, "deptId");
+          if (this.deptOptions.length == 0) {
+            const noResultsOptions = { deptId: this.form.parentId, deptName: this.form.parentName, children: [] };
+            this.deptOptions.push(noResultsOptions);
+          }
+        });
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm: function() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.deptId != undefined) {
+            updateDept(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addDept(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      this.$modal.confirm('鏄惁纭鍒犻櫎鍚嶇О涓�"' + row.deptName + '"鐨勬暟鎹」锛�').then(function() {
+        return delDept(row.deptId);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/system/dict/data.vue b/jcdm-ui/src/views/system/dict/data.vue
new file mode 100644
index 0000000..3befe4a
--- /dev/null
+++ b/jcdm-ui/src/views/system/dict/data.vue
@@ -0,0 +1,402 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="瀛楀吀鍚嶇О" prop="dictType">
+        <el-select v-model="queryParams.dictType">
+          <el-option
+            v-for="item in typeOptions"
+            :key="item.dictId"
+            :label="item.dictName"
+            :value="item.dictType"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="瀛楀吀鏍囩" prop="dictLabel">
+        <el-input
+          v-model="queryParams.dictLabel"
+          placeholder="璇疯緭鍏ュ瓧鍏告爣绛�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="鐘舵��" prop="status">
+        <el-select v-model="queryParams.status" placeholder="鏁版嵁鐘舵��" clearable>
+          <el-option
+            v-for="dict in dict.type.sys_normal_disable"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['system:dict:add']"
+        >鏂板</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['system:dict:edit']"
+        >淇敼</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['system:dict:remove']"
+        >鍒犻櫎</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['system:dict:export']"
+        >瀵煎嚭</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-close"
+          size="mini"
+          @click="handleClose"
+        >鍏抽棴</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="dataList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="瀛楀吀缂栫爜" align="center" prop="dictCode" />
+      <el-table-column label="瀛楀吀鏍囩" align="center" prop="dictLabel">
+        <template slot-scope="scope">
+          <span v-if="(scope.row.listClass == '' || scope.row.listClass == 'default') && (scope.row.cssClass == '' || scope.row.cssClass == null)">{{ scope.row.dictLabel }}</span>
+          <el-tag v-else :type="scope.row.listClass == 'primary' ? '' : scope.row.listClass" :class="scope.row.cssClass">{{ scope.row.dictLabel }}</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="瀛楀吀閿��" align="center" prop="dictValue" />
+      <el-table-column label="瀛楀吀鎺掑簭" align="center" prop="dictSort" />
+      <el-table-column label="鐘舵��" align="center" prop="status">
+        <template slot-scope="scope">
+          <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="澶囨敞" align="center" prop="remark" :show-overflow-tooltip="true" />
+      <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['system:dict:edit']"
+          >淇敼</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['system:dict:remove']"
+          >鍒犻櫎</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 娣诲姞鎴栦慨鏀瑰弬鏁伴厤缃璇濇 -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="瀛楀吀绫诲瀷">
+          <el-input v-model="form.dictType" :disabled="true" />
+        </el-form-item>
+        <el-form-item label="鏁版嵁鏍囩" prop="dictLabel">
+          <el-input v-model="form.dictLabel" placeholder="璇疯緭鍏ユ暟鎹爣绛�" />
+        </el-form-item>
+        <el-form-item label="鏁版嵁閿��" prop="dictValue">
+          <el-input v-model="form.dictValue" placeholder="璇疯緭鍏ユ暟鎹敭鍊�" />
+        </el-form-item>
+        <el-form-item label="鏍峰紡灞炴��" prop="cssClass">
+          <el-input v-model="form.cssClass" placeholder="璇疯緭鍏ユ牱寮忓睘鎬�" />
+        </el-form-item>
+        <el-form-item label="鏄剧ず鎺掑簭" prop="dictSort">
+          <el-input-number v-model="form.dictSort" controls-position="right" :min="0" />
+        </el-form-item>
+        <el-form-item label="鍥炴樉鏍峰紡" prop="listClass">
+          <el-select v-model="form.listClass">
+            <el-option
+              v-for="item in listClassOptions"
+              :key="item.value"
+              :label="item.label + '(' + item.value + ')'"
+              :value="item.value"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="鐘舵��" prop="status">
+          <el-radio-group v-model="form.status">
+            <el-radio
+              v-for="dict in dict.type.sys_normal_disable"
+              :key="dict.value"
+              :label="dict.value"
+            >{{dict.label}}</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="澶囨敞" prop="remark">
+          <el-input v-model="form.remark" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�"></el-input>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listData, getData, delData, addData, updateData } from "@/api/system/dict/data";
+import { optionselect as getDictOptionselect, getType } from "@/api/system/dict/type";
+
+export default {
+  name: "Data",
+  dicts: ['sys_normal_disable'],
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 瀛楀吀琛ㄦ牸鏁版嵁
+      dataList: [],
+      // 榛樿瀛楀吀绫诲瀷
+      defaultDictType: "",
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏁版嵁鏍囩鍥炴樉鏍峰紡
+      listClassOptions: [
+        {
+          value: "default",
+          label: "榛樿"
+        },
+        {
+          value: "primary",
+          label: "涓昏"
+        },
+        {
+          value: "success",
+          label: "鎴愬姛"
+        },
+        {
+          value: "info",
+          label: "淇℃伅"
+        },
+        {
+          value: "warning",
+          label: "璀﹀憡"
+        },
+        {
+          value: "danger",
+          label: "鍗遍櫓"
+        }
+      ],
+      // 绫诲瀷鏁版嵁瀛楀吀
+      typeOptions: [],
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        dictType: undefined,
+        dictLabel: undefined,
+        status: undefined
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        dictLabel: [
+          { required: true, message: "鏁版嵁鏍囩涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        dictValue: [
+          { required: true, message: "鏁版嵁閿�间笉鑳戒负绌�", trigger: "blur" }
+        ],
+        dictSort: [
+          { required: true, message: "鏁版嵁椤哄簭涓嶈兘涓虹┖", trigger: "blur" }
+        ]
+      }
+    };
+  },
+  created() {
+    const dictId = this.$route.params && this.$route.params.dictId;
+    this.getType(dictId);
+    this.getTypeList();
+  },
+  methods: {
+    /** 鏌ヨ瀛楀吀绫诲瀷璇︾粏 */
+    getType(dictId) {
+      getType(dictId).then(response => {
+        this.queryParams.dictType = response.data.dictType;
+        this.defaultDictType = response.data.dictType;
+        this.getList();
+      });
+    },
+    /** 鏌ヨ瀛楀吀绫诲瀷鍒楄〃 */
+    getTypeList() {
+      getDictOptionselect().then(response => {
+        this.typeOptions = response.data;
+      });
+    },
+    /** 鏌ヨ瀛楀吀鏁版嵁鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listData(this.queryParams).then(response => {
+        this.dataList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        dictCode: undefined,
+        dictLabel: undefined,
+        dictValue: undefined,
+        cssClass: undefined,
+        listClass: 'default',
+        dictSort: 0,
+        status: "0",
+        remark: undefined
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 杩斿洖鎸夐挳鎿嶄綔 */
+    handleClose() {
+      const obj = { path: "/system/dict" };
+      this.$tab.closeOpenPage(obj);
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.queryParams.dictType = this.defaultDictType;
+      this.handleQuery();
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "娣诲姞瀛楀吀鏁版嵁";
+      this.form.dictType = this.queryParams.dictType;
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.dictCode)
+      this.single = selection.length!=1
+      this.multiple = !selection.length
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.reset();
+      const dictCode = row.dictCode || this.ids
+      getData(dictCode).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "淇敼瀛楀吀鏁版嵁";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm: function() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.dictCode != undefined) {
+            updateData(this.form).then(response => {
+              this.$store.dispatch('dict/removeDict', this.queryParams.dictType);
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addData(this.form).then(response => {
+              this.$store.dispatch('dict/removeDict', this.queryParams.dictType);
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const dictCodes = row.dictCode || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎瀛楀吀缂栫爜涓�"' + dictCodes + '"鐨勬暟鎹」锛�').then(function() {
+        return delData(dictCodes);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+        this.$store.dispatch('dict/removeDict', this.queryParams.dictType);
+      }).catch(() => {});
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('system/dict/data/export', {
+        ...this.queryParams
+      }, `data_${new Date().getTime()}.xlsx`)
+    }
+  }
+};
+</script>
\ No newline at end of file
diff --git a/jcdm-ui/src/views/system/dict/index.vue b/jcdm-ui/src/views/system/dict/index.vue
new file mode 100644
index 0000000..6ca5457
--- /dev/null
+++ b/jcdm-ui/src/views/system/dict/index.vue
@@ -0,0 +1,347 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="瀛楀吀鍚嶇О" prop="dictName">
+        <el-input
+          v-model="queryParams.dictName"
+          placeholder="璇疯緭鍏ュ瓧鍏稿悕绉�"
+          clearable
+          style="width: 240px"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="瀛楀吀绫诲瀷" prop="dictType">
+        <el-input
+          v-model="queryParams.dictType"
+          placeholder="璇疯緭鍏ュ瓧鍏哥被鍨�"
+          clearable
+          style="width: 240px"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="鐘舵��" prop="status">
+        <el-select
+          v-model="queryParams.status"
+          placeholder="瀛楀吀鐘舵��"
+          clearable
+          style="width: 240px"
+        >
+          <el-option
+            v-for="dict in dict.type.sys_normal_disable"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="鍒涘缓鏃堕棿">
+        <el-date-picker
+          v-model="dateRange"
+          style="width: 240px"
+          value-format="yyyy-MM-dd"
+          type="daterange"
+          range-separator="-"
+          start-placeholder="寮�濮嬫棩鏈�"
+          end-placeholder="缁撴潫鏃ユ湡"
+        ></el-date-picker>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['system:dict:add']"
+        >鏂板</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['system:dict:edit']"
+        >淇敼</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['system:dict:remove']"
+        >鍒犻櫎</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['system:dict:export']"
+        >瀵煎嚭</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-refresh"
+          size="mini"
+          @click="handleRefreshCache"
+          v-hasPermi="['system:dict:remove']"
+        >鍒锋柊缂撳瓨</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="typeList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="瀛楀吀缂栧彿" align="center" prop="dictId" />
+      <el-table-column label="瀛楀吀鍚嶇О" align="center" prop="dictName" :show-overflow-tooltip="true" />
+      <el-table-column label="瀛楀吀绫诲瀷" align="center" :show-overflow-tooltip="true">
+        <template slot-scope="scope">
+          <router-link :to="'/system/dict-data/index/' + scope.row.dictId" class="link-type">
+            <span>{{ scope.row.dictType }}</span>
+          </router-link>
+        </template>
+      </el-table-column>
+      <el-table-column label="鐘舵��" align="center" prop="status">
+        <template slot-scope="scope">
+          <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="澶囨敞" align="center" prop="remark" :show-overflow-tooltip="true" />
+      <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['system:dict:edit']"
+          >淇敼</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['system:dict:remove']"
+          >鍒犻櫎</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 娣诲姞鎴栦慨鏀瑰弬鏁伴厤缃璇濇 -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="瀛楀吀鍚嶇О" prop="dictName">
+          <el-input v-model="form.dictName" placeholder="璇疯緭鍏ュ瓧鍏稿悕绉�" />
+        </el-form-item>
+        <el-form-item label="瀛楀吀绫诲瀷" prop="dictType">
+          <el-input v-model="form.dictType" placeholder="璇疯緭鍏ュ瓧鍏哥被鍨�" />
+        </el-form-item>
+        <el-form-item label="鐘舵��" prop="status">
+          <el-radio-group v-model="form.status">
+            <el-radio
+              v-for="dict in dict.type.sys_normal_disable"
+              :key="dict.value"
+              :label="dict.value"
+            >{{dict.label}}</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="澶囨敞" prop="remark">
+          <el-input v-model="form.remark" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�"></el-input>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listType, getType, delType, addType, updateType, refreshCache } from "@/api/system/dict/type";
+
+export default {
+  name: "Dict",
+  dicts: ['sys_normal_disable'],
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 瀛楀吀琛ㄦ牸鏁版嵁
+      typeList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏃ユ湡鑼冨洿
+      dateRange: [],
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        dictName: undefined,
+        dictType: undefined,
+        status: undefined
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        dictName: [
+          { required: true, message: "瀛楀吀鍚嶇О涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        dictType: [
+          { required: true, message: "瀛楀吀绫诲瀷涓嶈兘涓虹┖", trigger: "blur" }
+        ]
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 鏌ヨ瀛楀吀绫诲瀷鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listType(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
+          this.typeList = response.rows;
+          this.total = response.total;
+          this.loading = false;
+        }
+      );
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        dictId: undefined,
+        dictName: undefined,
+        dictType: undefined,
+        status: "0",
+        remark: undefined
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.dateRange = [];
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "娣诲姞瀛楀吀绫诲瀷";
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.dictId)
+      this.single = selection.length!=1
+      this.multiple = !selection.length
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.reset();
+      const dictId = row.dictId || this.ids
+      getType(dictId).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "淇敼瀛楀吀绫诲瀷";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm: function() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.dictId != undefined) {
+            updateType(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addType(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const dictIds = row.dictId || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎瀛楀吀缂栧彿涓�"' + dictIds + '"鐨勬暟鎹」锛�').then(function() {
+        return delType(dictIds);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('system/dict/type/export', {
+        ...this.queryParams
+      }, `type_${new Date().getTime()}.xlsx`)
+    },
+    /** 鍒锋柊缂撳瓨鎸夐挳鎿嶄綔 */
+    handleRefreshCache() {
+      refreshCache().then(() => {
+        this.$modal.msgSuccess("鍒锋柊鎴愬姛");
+        this.$store.dispatch('dict/cleanDict');
+      });
+    }
+  }
+};
+</script>
\ No newline at end of file
diff --git a/jcdm-ui/src/views/system/menu/index.vue b/jcdm-ui/src/views/system/menu/index.vue
new file mode 100644
index 0000000..c703fa0
--- /dev/null
+++ b/jcdm-ui/src/views/system/menu/index.vue
@@ -0,0 +1,452 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch">
+      <el-form-item label="鑿滃崟鍚嶇О" prop="menuName">
+        <el-input
+          v-model="queryParams.menuName"
+          placeholder="璇疯緭鍏ヨ彍鍗曞悕绉�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="鐘舵��" prop="status">
+        <el-select v-model="queryParams.status" placeholder="鑿滃崟鐘舵��" clearable>
+          <el-option
+            v-for="dict in dict.type.sys_normal_disable"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['system:menu:add']"
+        >鏂板</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="info"
+          plain
+          icon="el-icon-sort"
+          size="mini"
+          @click="toggleExpandAll"
+        >灞曞紑/鎶樺彔</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table
+      v-if="refreshTable"
+      v-loading="loading"
+      :data="menuList"
+      row-key="menuId"
+      :default-expand-all="isExpandAll"
+      :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
+    >
+      <el-table-column prop="menuName" label="鑿滃崟鍚嶇О" :show-overflow-tooltip="true" width="160"></el-table-column>
+      <el-table-column prop="icon" label="鍥炬爣" align="center" width="100">
+        <template slot-scope="scope">
+          <svg-icon :icon-class="scope.row.icon" />
+        </template>
+      </el-table-column>
+      <el-table-column prop="orderNum" label="鎺掑簭" width="60"></el-table-column>
+      <el-table-column prop="perms" label="鏉冮檺鏍囪瘑" :show-overflow-tooltip="true"></el-table-column>
+      <el-table-column prop="component" label="缁勪欢璺緞" :show-overflow-tooltip="true"></el-table-column>
+      <el-table-column prop="status" label="鐘舵��" width="80">
+        <template slot-scope="scope">
+          <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['system:menu:edit']"
+          >淇敼</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-plus"
+            @click="handleAdd(scope.row)"
+            v-hasPermi="['system:menu:add']"
+          >鏂板</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['system:menu:remove']"
+          >鍒犻櫎</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- 娣诲姞鎴栦慨鏀硅彍鍗曞璇濇 -->
+    <el-dialog :title="title" :visible.sync="open" width="680px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="100px">
+        <el-row>
+          <el-col :span="24">
+            <el-form-item label="涓婄骇鑿滃崟" prop="parentId">
+              <treeselect
+                v-model="form.parentId"
+                :options="menuOptions"
+                :normalizer="normalizer"
+                :show-count="true"
+                placeholder="閫夋嫨涓婄骇鑿滃崟"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="24">
+            <el-form-item label="鑿滃崟绫诲瀷" prop="menuType">
+              <el-radio-group v-model="form.menuType">
+                <el-radio label="M">鐩綍</el-radio>
+                <el-radio label="C">鑿滃崟</el-radio>
+                <el-radio label="F">鎸夐挳</el-radio>
+              </el-radio-group>
+            </el-form-item>
+          </el-col>
+          <el-col :span="24" v-if="form.menuType != 'F'">
+            <el-form-item label="鑿滃崟鍥炬爣" prop="icon">
+              <el-popover
+                placement="bottom-start"
+                width="460"
+                trigger="click"
+                @show="$refs['iconSelect'].reset()"
+              >
+                <IconSelect ref="iconSelect" @selected="selected" :active-icon="form.icon" />
+                <el-input slot="reference" v-model="form.icon" placeholder="鐐瑰嚮閫夋嫨鍥炬爣" readonly>
+                  <svg-icon
+                    v-if="form.icon"
+                    slot="prefix"
+                    :icon-class="form.icon"
+                    style="width: 25px;"
+                  />
+                  <i v-else slot="prefix" class="el-icon-search el-input__icon" />
+                </el-input>
+              </el-popover>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鑿滃崟鍚嶇О" prop="menuName">
+              <el-input v-model="form.menuName" placeholder="璇疯緭鍏ヨ彍鍗曞悕绉�" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鏄剧ず鎺掑簭" prop="orderNum">
+              <el-input-number v-model="form.orderNum" controls-position="right" :min="0" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12" v-if="form.menuType != 'F'">
+            <el-form-item prop="isFrame">
+              <span slot="label">
+                <el-tooltip content="閫夋嫨鏄閾惧垯璺敱鍦板潃闇�瑕佷互`http(s)://`寮�澶�" placement="top">
+                <i class="el-icon-question"></i>
+                </el-tooltip>
+                鏄惁澶栭摼
+              </span>
+              <el-radio-group v-model="form.isFrame">
+                <el-radio label="0">鏄�</el-radio>
+                <el-radio label="1">鍚�</el-radio>
+              </el-radio-group>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12" v-if="form.menuType != 'F'">
+            <el-form-item prop="path">
+              <span slot="label">
+                <el-tooltip content="璁块棶鐨勮矾鐢卞湴鍧�锛屽锛歚user`锛屽澶栫綉鍦板潃闇�鍐呴摼璁块棶鍒欎互`http(s)://`寮�澶�" placement="top">
+                <i class="el-icon-question"></i>
+                </el-tooltip>
+                璺敱鍦板潃
+              </span>
+              <el-input v-model="form.path" placeholder="璇疯緭鍏ヨ矾鐢卞湴鍧�" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12" v-if="form.menuType == 'C'">
+            <el-form-item prop="component">
+              <span slot="label">
+                <el-tooltip content="璁块棶鐨勭粍浠惰矾寰勶紝濡傦細`system/user/index`锛岄粯璁ゅ湪`views`鐩綍涓�" placement="top">
+                <i class="el-icon-question"></i>
+                </el-tooltip>
+                缁勪欢璺緞
+              </span>
+              <el-input v-model="form.component" placeholder="璇疯緭鍏ョ粍浠惰矾寰�" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12" v-if="form.menuType != 'M'">
+            <el-form-item prop="perms">
+              <el-input v-model="form.perms" placeholder="璇疯緭鍏ユ潈闄愭爣璇�" maxlength="100" />
+              <span slot="label">
+                <el-tooltip content="鎺у埗鍣ㄤ腑瀹氫箟鐨勬潈闄愬瓧绗︼紝濡傦細@PreAuthorize(`@ss.hasPermi('system:user:list')`)" placement="top">
+                <i class="el-icon-question"></i>
+                </el-tooltip>
+                鏉冮檺瀛楃
+              </span>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12" v-if="form.menuType == 'C'">
+            <el-form-item prop="query">
+              <el-input v-model="form.query" placeholder="璇疯緭鍏ヨ矾鐢卞弬鏁�" maxlength="255" />
+              <span slot="label">
+                <el-tooltip content='璁块棶璺敱鐨勯粯璁や紶閫掑弬鏁帮紝濡傦細`{"id": 1, "name": "ry"}`' placement="top">
+                <i class="el-icon-question"></i>
+                </el-tooltip>
+                璺敱鍙傛暟
+              </span>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12" v-if="form.menuType == 'C'">
+            <el-form-item prop="isCache">
+              <span slot="label">
+                <el-tooltip content="閫夋嫨鏄垯浼氳`keep-alive`缂撳瓨锛岄渶瑕佸尮閰嶇粍浠剁殑`name`鍜屽湴鍧�淇濇寔涓�鑷�" placement="top">
+                <i class="el-icon-question"></i>
+                </el-tooltip>
+                鏄惁缂撳瓨
+              </span>
+              <el-radio-group v-model="form.isCache">
+                <el-radio label="0">缂撳瓨</el-radio>
+                <el-radio label="1">涓嶇紦瀛�</el-radio>
+              </el-radio-group>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12" v-if="form.menuType != 'F'">
+            <el-form-item prop="visible">
+              <span slot="label">
+                <el-tooltip content="閫夋嫨闅愯棌鍒欒矾鐢卞皢涓嶄細鍑虹幇鍦ㄤ晶杈规爮锛屼絾浠嶇劧鍙互璁块棶" placement="top">
+                <i class="el-icon-question"></i>
+                </el-tooltip>
+                鏄剧ず鐘舵��
+              </span>
+              <el-radio-group v-model="form.visible">
+                <el-radio
+                  v-for="dict in dict.type.sys_show_hide"
+                  :key="dict.value"
+                  :label="dict.value"
+                >{{dict.label}}</el-radio>
+              </el-radio-group>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item prop="status">
+              <span slot="label">
+                <el-tooltip content="閫夋嫨鍋滅敤鍒欒矾鐢卞皢涓嶄細鍑虹幇鍦ㄤ晶杈规爮锛屼篃涓嶈兘琚闂�" placement="top">
+                <i class="el-icon-question"></i>
+                </el-tooltip>
+                鑿滃崟鐘舵��
+              </span>
+              <el-radio-group v-model="form.status">
+                <el-radio
+                  v-for="dict in dict.type.sys_normal_disable"
+                  :key="dict.value"
+                  :label="dict.value"
+                >{{dict.label}}</el-radio>
+              </el-radio-group>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listMenu, getMenu, delMenu, addMenu, updateMenu } from "@/api/system/menu";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+import IconSelect from "@/components/IconSelect";
+
+export default {
+  name: "Menu",
+  dicts: ['sys_show_hide', 'sys_normal_disable'],
+  components: { Treeselect, IconSelect },
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鑿滃崟琛ㄦ牸鏍戞暟鎹�
+      menuList: [],
+      // 鑿滃崟鏍戦�夐」
+      menuOptions: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏄惁灞曞紑锛岄粯璁ゅ叏閮ㄦ姌鍙�
+      isExpandAll: false,
+      // 閲嶆柊娓叉煋琛ㄦ牸鐘舵��
+      refreshTable: true,
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        menuName: undefined,
+        visible: undefined
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        menuName: [
+          { required: true, message: "鑿滃崟鍚嶇О涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        orderNum: [
+          { required: true, message: "鑿滃崟椤哄簭涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        path: [
+          { required: true, message: "璺敱鍦板潃涓嶈兘涓虹┖", trigger: "blur" }
+        ]
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    // 閫夋嫨鍥炬爣
+    selected(name) {
+      this.form.icon = name;
+    },
+    /** 鏌ヨ鑿滃崟鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listMenu(this.queryParams).then(response => {
+        this.menuList = this.handleTree(response.data, "menuId");
+        this.loading = false;
+      });
+    },
+    /** 杞崲鑿滃崟鏁版嵁缁撴瀯 */
+    normalizer(node) {
+      if (node.children && !node.children.length) {
+        delete node.children;
+      }
+      return {
+        id: node.menuId,
+        label: node.menuName,
+        children: node.children
+      };
+    },
+    /** 鏌ヨ鑿滃崟涓嬫媺鏍戠粨鏋� */
+    getTreeselect() {
+      listMenu().then(response => {
+        this.menuOptions = [];
+        const menu = { menuId: 0, menuName: '涓荤被鐩�', children: [] };
+        menu.children = this.handleTree(response.data, "menuId");
+        this.menuOptions.push(menu);
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        menuId: undefined,
+        parentId: 0,
+        menuName: undefined,
+        icon: undefined,
+        menuType: "M",
+        orderNum: undefined,
+        isFrame: "1",
+        isCache: "0",
+        visible: "0",
+        status: "0"
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd(row) {
+      this.reset();
+      this.getTreeselect();
+      if (row != null && row.menuId) {
+        this.form.parentId = row.menuId;
+      } else {
+        this.form.parentId = 0;
+      }
+      this.open = true;
+      this.title = "娣诲姞鑿滃崟";
+    },
+    /** 灞曞紑/鎶樺彔鎿嶄綔 */
+    toggleExpandAll() {
+      this.refreshTable = false;
+      this.isExpandAll = !this.isExpandAll;
+      this.$nextTick(() => {
+        this.refreshTable = true;
+      });
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.reset();
+      this.getTreeselect();
+      getMenu(row.menuId).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "淇敼鑿滃崟";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm: function() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.menuId != undefined) {
+            updateMenu(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addMenu(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      this.$modal.confirm('鏄惁纭鍒犻櫎鍚嶇О涓�"' + row.menuName + '"鐨勬暟鎹」锛�').then(function() {
+        return delMenu(row.menuId);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/system/notice/index.vue b/jcdm-ui/src/views/system/notice/index.vue
new file mode 100644
index 0000000..7982b54
--- /dev/null
+++ b/jcdm-ui/src/views/system/notice/index.vue
@@ -0,0 +1,312 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="鍏憡鏍囬" prop="noticeTitle">
+        <el-input
+          v-model="queryParams.noticeTitle"
+          placeholder="璇疯緭鍏ュ叕鍛婃爣棰�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="鎿嶄綔浜哄憳" prop="createBy">
+        <el-input
+          v-model="queryParams.createBy"
+          placeholder="璇疯緭鍏ユ搷浣滀汉鍛�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="绫诲瀷" prop="noticeType">
+        <el-select v-model="queryParams.noticeType" placeholder="鍏憡绫诲瀷" clearable>
+          <el-option
+            v-for="dict in dict.type.sys_notice_type"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['system:notice:add']"
+        >鏂板</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['system:notice:edit']"
+        >淇敼</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['system:notice:remove']"
+        >鍒犻櫎</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="noticeList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="搴忓彿" align="center" prop="noticeId" width="100" />
+      <el-table-column
+        label="鍏憡鏍囬"
+        align="center"
+        prop="noticeTitle"
+        :show-overflow-tooltip="true"
+      />
+      <el-table-column label="鍏憡绫诲瀷" align="center" prop="noticeType" width="100">
+        <template slot-scope="scope">
+          <dict-tag :options="dict.type.sys_notice_type" :value="scope.row.noticeType"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="鐘舵��" align="center" prop="status" width="100">
+        <template slot-scope="scope">
+          <dict-tag :options="dict.type.sys_notice_status" :value="scope.row.status"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="鍒涘缓鑰�" align="center" prop="createBy" width="100" />
+      <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="100">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['system:notice:edit']"
+          >淇敼</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['system:notice:remove']"
+          >鍒犻櫎</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 娣诲姞鎴栦慨鏀瑰叕鍛婂璇濇 -->
+    <el-dialog :title="title" :visible.sync="open" width="780px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="鍏憡鏍囬" prop="noticeTitle">
+              <el-input v-model="form.noticeTitle" placeholder="璇疯緭鍏ュ叕鍛婃爣棰�" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鍏憡绫诲瀷" prop="noticeType">
+              <el-select v-model="form.noticeType" placeholder="璇烽�夋嫨鍏憡绫诲瀷">
+                <el-option
+                  v-for="dict in dict.type.sys_notice_type"
+                  :key="dict.value"
+                  :label="dict.label"
+                  :value="dict.value"
+                ></el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="24">
+            <el-form-item label="鐘舵��">
+              <el-radio-group v-model="form.status">
+                <el-radio
+                  v-for="dict in dict.type.sys_notice_status"
+                  :key="dict.value"
+                  :label="dict.value"
+                >{{dict.label}}</el-radio>
+              </el-radio-group>
+            </el-form-item>
+          </el-col>
+          <el-col :span="24">
+            <el-form-item label="鍐呭">
+              <editor v-model="form.noticeContent" :min-height="192"/>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listNotice, getNotice, delNotice, addNotice, updateNotice } from "@/api/system/notice";
+
+export default {
+  name: "Notice",
+  dicts: ['sys_notice_status', 'sys_notice_type'],
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 鍏憡琛ㄦ牸鏁版嵁
+      noticeList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        noticeTitle: undefined,
+        createBy: undefined,
+        status: undefined
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        noticeTitle: [
+          { required: true, message: "鍏憡鏍囬涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        noticeType: [
+          { required: true, message: "鍏憡绫诲瀷涓嶈兘涓虹┖", trigger: "change" }
+        ]
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 鏌ヨ鍏憡鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listNotice(this.queryParams).then(response => {
+        this.noticeList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        noticeId: undefined,
+        noticeTitle: undefined,
+        noticeType: undefined,
+        noticeContent: undefined,
+        status: "0"
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.noticeId)
+      this.single = selection.length!=1
+      this.multiple = !selection.length
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "娣诲姞鍏憡";
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.reset();
+      const noticeId = row.noticeId || this.ids
+      getNotice(noticeId).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "淇敼鍏憡";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm: function() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.noticeId != undefined) {
+            updateNotice(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addNotice(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const noticeIds = row.noticeId || this.ids
+      this.$modal.confirm('鏄惁纭鍒犻櫎鍏憡缂栧彿涓�"' + noticeIds + '"鐨勬暟鎹」锛�').then(function() {
+        return delNotice(noticeIds);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/system/post/index.vue b/jcdm-ui/src/views/system/post/index.vue
new file mode 100644
index 0000000..444bf63
--- /dev/null
+++ b/jcdm-ui/src/views/system/post/index.vue
@@ -0,0 +1,309 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="宀椾綅缂栫爜" prop="postCode">
+        <el-input
+          v-model="queryParams.postCode"
+          placeholder="璇疯緭鍏ュ矖浣嶇紪鐮�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="宀椾綅鍚嶇О" prop="postName">
+        <el-input
+          v-model="queryParams.postName"
+          placeholder="璇疯緭鍏ュ矖浣嶅悕绉�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="鐘舵��" prop="status">
+        <el-select v-model="queryParams.status" placeholder="宀椾綅鐘舵��" clearable>
+          <el-option
+            v-for="dict in dict.type.sys_normal_disable"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['system:post:add']"
+        >鏂板</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['system:post:edit']"
+        >淇敼</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['system:post:remove']"
+        >鍒犻櫎</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['system:post:export']"
+        >瀵煎嚭</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="postList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="宀椾綅缂栧彿" align="center" prop="postId" />
+      <el-table-column label="宀椾綅缂栫爜" align="center" prop="postCode" />
+      <el-table-column label="宀椾綅鍚嶇О" align="center" prop="postName" />
+      <el-table-column label="宀椾綅鎺掑簭" align="center" prop="postSort" />
+      <el-table-column label="鐘舵��" align="center" prop="status">
+        <template slot-scope="scope">
+          <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['system:post:edit']"
+          >淇敼</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['system:post:remove']"
+          >鍒犻櫎</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 娣诲姞鎴栦慨鏀瑰矖浣嶅璇濇 -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="宀椾綅鍚嶇О" prop="postName">
+          <el-input v-model="form.postName" placeholder="璇疯緭鍏ュ矖浣嶅悕绉�" />
+        </el-form-item>
+        <el-form-item label="宀椾綅缂栫爜" prop="postCode">
+          <el-input v-model="form.postCode" placeholder="璇疯緭鍏ョ紪鐮佸悕绉�" />
+        </el-form-item>
+        <el-form-item label="宀椾綅椤哄簭" prop="postSort">
+          <el-input-number v-model="form.postSort" controls-position="right" :min="0" />
+        </el-form-item>
+        <el-form-item label="宀椾綅鐘舵��" prop="status">
+          <el-radio-group v-model="form.status">
+            <el-radio
+              v-for="dict in dict.type.sys_normal_disable"
+              :key="dict.value"
+              :label="dict.value"
+            >{{dict.label}}</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="澶囨敞" prop="remark">
+          <el-input v-model="form.remark" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listPost, getPost, delPost, addPost, updatePost } from "@/api/system/post";
+
+export default {
+  name: "Post",
+  dicts: ['sys_normal_disable'],
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 宀椾綅琛ㄦ牸鏁版嵁
+      postList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        postCode: undefined,
+        postName: undefined,
+        status: undefined
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        postName: [
+          { required: true, message: "宀椾綅鍚嶇О涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        postCode: [
+          { required: true, message: "宀椾綅缂栫爜涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        postSort: [
+          { required: true, message: "宀椾綅椤哄簭涓嶈兘涓虹┖", trigger: "blur" }
+        ]
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 鏌ヨ宀椾綅鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listPost(this.queryParams).then(response => {
+        this.postList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        postId: undefined,
+        postCode: undefined,
+        postName: undefined,
+        postSort: 0,
+        status: "0",
+        remark: undefined
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.postId)
+      this.single = selection.length!=1
+      this.multiple = !selection.length
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "娣诲姞宀椾綅";
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.reset();
+      const postId = row.postId || this.ids
+      getPost(postId).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "淇敼宀椾綅";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm: function() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.postId != undefined) {
+            updatePost(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addPost(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const postIds = row.postId || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎宀椾綅缂栧彿涓�"' + postIds + '"鐨勬暟鎹」锛�').then(function() {
+        return delPost(postIds);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('system/post/export', {
+        ...this.queryParams
+      }, `post_${new Date().getTime()}.xlsx`)
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/system/role/authUser.vue b/jcdm-ui/src/views/system/role/authUser.vue
new file mode 100644
index 0000000..147aa33
--- /dev/null
+++ b/jcdm-ui/src/views/system/role/authUser.vue
@@ -0,0 +1,199 @@
+<template>
+  <div class="app-container">
+     <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch">
+      <el-form-item label="鐢ㄦ埛鍚嶇О" prop="userName">
+        <el-input
+          v-model="queryParams.userName"
+          placeholder="璇疯緭鍏ョ敤鎴峰悕绉�"
+          clearable
+          style="width: 240px"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="鎵嬫満鍙风爜" prop="phonenumber">
+        <el-input
+          v-model="queryParams.phonenumber"
+          placeholder="璇疯緭鍏ユ墜鏈哄彿鐮�"
+          clearable
+          style="width: 240px"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="openSelectUser"
+          v-hasPermi="['system:role:add']"
+        >娣诲姞鐢ㄦ埛</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-circle-close"
+          size="mini"
+          :disabled="multiple"
+          @click="cancelAuthUserAll"
+          v-hasPermi="['system:role:remove']"
+        >鎵归噺鍙栨秷鎺堟潈</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-close"
+          size="mini"
+          @click="handleClose"
+        >鍏抽棴</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="鐢ㄦ埛鍚嶇О" prop="userName" :show-overflow-tooltip="true" />
+      <el-table-column label="鐢ㄦ埛鏄电О" prop="nickName" :show-overflow-tooltip="true" />
+      <el-table-column label="閭" prop="email" :show-overflow-tooltip="true" />
+      <el-table-column label="鎵嬫満" prop="phonenumber" :show-overflow-tooltip="true" />
+      <el-table-column label="鐘舵��" align="center" prop="status">
+        <template slot-scope="scope">
+          <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-circle-close"
+            @click="cancelAuthUser(scope.row)"
+            v-hasPermi="['system:role:remove']"
+          >鍙栨秷鎺堟潈</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+    <select-user ref="select" :roleId="queryParams.roleId" @ok="handleQuery" />
+  </div>
+</template>
+
+<script>
+import { allocatedUserList, authUserCancel, authUserCancelAll } from "@/api/system/role";
+import selectUser from "./selectUser";
+
+export default {
+  name: "AuthUser",
+  dicts: ['sys_normal_disable'],
+  components: { selectUser },
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      // 閫変腑鐢ㄦ埛缁�
+      userIds: [],
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 鐢ㄦ埛琛ㄦ牸鏁版嵁
+      userList: [],
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        roleId: undefined,
+        userName: undefined,
+        phonenumber: undefined
+      }
+    };
+  },
+  created() {
+    const roleId = this.$route.params && this.$route.params.roleId;
+    if (roleId) {
+      this.queryParams.roleId = roleId;
+      this.getList();
+    }
+  },
+  methods: {
+    /** 鏌ヨ鎺堟潈鐢ㄦ埛鍒楄〃 */
+    getList() {
+      this.loading = true;
+      allocatedUserList(this.queryParams).then(response => {
+          this.userList = response.rows;
+          this.total = response.total;
+          this.loading = false;
+        }
+      );
+    },
+    // 杩斿洖鎸夐挳
+    handleClose() {
+      const obj = { path: "/system/role" };
+      this.$tab.closeOpenPage(obj);
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.userIds = selection.map(item => item.userId)
+      this.multiple = !selection.length
+    },
+    /** 鎵撳紑鎺堟潈鐢ㄦ埛琛ㄥ脊绐� */
+    openSelectUser() {
+      this.$refs.select.show();
+    },
+    /** 鍙栨秷鎺堟潈鎸夐挳鎿嶄綔 */
+    cancelAuthUser(row) {
+      const roleId = this.queryParams.roleId;
+      this.$modal.confirm('纭瑕佸彇娑堣鐢ㄦ埛"' + row.userName + '"瑙掕壊鍚楋紵').then(function() {
+        return authUserCancel({ userId: row.userId, roleId: roleId });
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍙栨秷鎺堟潈鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 鎵归噺鍙栨秷鎺堟潈鎸夐挳鎿嶄綔 */
+    cancelAuthUserAll(row) {
+      const roleId = this.queryParams.roleId;
+      const userIds = this.userIds.join(",");
+      this.$modal.confirm('鏄惁鍙栨秷閫変腑鐢ㄦ埛鎺堟潈鏁版嵁椤癸紵').then(function() {
+        return authUserCancelAll({ roleId: roleId, userIds: userIds });
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍙栨秷鎺堟潈鎴愬姛");
+      }).catch(() => {});
+    }
+  }
+};
+</script>
\ No newline at end of file
diff --git a/jcdm-ui/src/views/system/role/index.vue b/jcdm-ui/src/views/system/role/index.vue
new file mode 100644
index 0000000..fb3b5ef
--- /dev/null
+++ b/jcdm-ui/src/views/system/role/index.vue
@@ -0,0 +1,605 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch">
+      <el-form-item label="瑙掕壊鍚嶇О" prop="roleName">
+        <el-input
+          v-model="queryParams.roleName"
+          placeholder="璇疯緭鍏ヨ鑹插悕绉�"
+          clearable
+          style="width: 240px"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="鏉冮檺瀛楃" prop="roleKey">
+        <el-input
+          v-model="queryParams.roleKey"
+          placeholder="璇疯緭鍏ユ潈闄愬瓧绗�"
+          clearable
+          style="width: 240px"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="鐘舵��" prop="status">
+        <el-select
+          v-model="queryParams.status"
+          placeholder="瑙掕壊鐘舵��"
+          clearable
+          style="width: 240px"
+        >
+          <el-option
+            v-for="dict in dict.type.sys_normal_disable"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="鍒涘缓鏃堕棿">
+        <el-date-picker
+          v-model="dateRange"
+          style="width: 240px"
+          value-format="yyyy-MM-dd"
+          type="daterange"
+          range-separator="-"
+          start-placeholder="寮�濮嬫棩鏈�"
+          end-placeholder="缁撴潫鏃ユ湡"
+        ></el-date-picker>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['system:role:add']"
+        >鏂板</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['system:role:edit']"
+        >淇敼</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['system:role:remove']"
+        >鍒犻櫎</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['system:role:export']"
+        >瀵煎嚭</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="roleList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="瑙掕壊缂栧彿" prop="roleId" width="120" />
+      <el-table-column label="瑙掕壊鍚嶇О" prop="roleName" :show-overflow-tooltip="true" width="150" />
+      <el-table-column label="鏉冮檺瀛楃" prop="roleKey" :show-overflow-tooltip="true" width="150" />
+      <el-table-column label="鏄剧ず椤哄簭" prop="roleSort" width="100" />
+      <el-table-column label="鐘舵��" align="center" width="100">
+        <template slot-scope="scope">
+          <el-switch
+            v-model="scope.row.status"
+            active-value="0"
+            inactive-value="1"
+            @change="handleStatusChange(scope.row)"
+          ></el-switch>
+        </template>
+      </el-table-column>
+      <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope" v-if="scope.row.roleId !== 1">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['system:role:edit']"
+          >淇敼</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['system:role:remove']"
+          >鍒犻櫎</el-button>
+          <el-dropdown size="mini" @command="(command) => handleCommand(command, scope.row)" v-hasPermi="['system:role:edit']">
+            <el-button size="mini" type="text" icon="el-icon-d-arrow-right">鏇村</el-button>
+            <el-dropdown-menu slot="dropdown">
+              <el-dropdown-item command="handleDataScope" icon="el-icon-circle-check"
+                v-hasPermi="['system:role:edit']">鏁版嵁鏉冮檺</el-dropdown-item>
+              <el-dropdown-item command="handleAuthUser" icon="el-icon-user"
+                v-hasPermi="['system:role:edit']">鍒嗛厤鐢ㄦ埛</el-dropdown-item>
+            </el-dropdown-menu>
+          </el-dropdown>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 娣诲姞鎴栦慨鏀硅鑹查厤缃璇濇 -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="100px">
+        <el-form-item label="瑙掕壊鍚嶇О" prop="roleName">
+          <el-input v-model="form.roleName" placeholder="璇疯緭鍏ヨ鑹插悕绉�" />
+        </el-form-item>
+        <el-form-item prop="roleKey">
+          <span slot="label">
+            <el-tooltip content="鎺у埗鍣ㄤ腑瀹氫箟鐨勬潈闄愬瓧绗︼紝濡傦細@PreAuthorize(`@ss.hasRole('admin')`)" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+            鏉冮檺瀛楃
+          </span>
+          <el-input v-model="form.roleKey" placeholder="璇疯緭鍏ユ潈闄愬瓧绗�" />
+        </el-form-item>
+        <el-form-item label="瑙掕壊椤哄簭" prop="roleSort">
+          <el-input-number v-model="form.roleSort" controls-position="right" :min="0" />
+        </el-form-item>
+        <el-form-item label="鐘舵��">
+          <el-radio-group v-model="form.status">
+            <el-radio
+              v-for="dict in dict.type.sys_normal_disable"
+              :key="dict.value"
+              :label="dict.value"
+            >{{dict.label}}</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="鑿滃崟鏉冮檺">
+          <el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand($event, 'menu')">灞曞紑/鎶樺彔</el-checkbox>
+          <el-checkbox v-model="menuNodeAll" @change="handleCheckedTreeNodeAll($event, 'menu')">鍏ㄩ��/鍏ㄤ笉閫�</el-checkbox>
+          <el-checkbox v-model="form.menuCheckStrictly" @change="handleCheckedTreeConnect($event, 'menu')">鐖跺瓙鑱斿姩</el-checkbox>
+          <el-tree
+            class="tree-border"
+            :data="menuOptions"
+            show-checkbox
+            ref="menu"
+            node-key="id"
+            :check-strictly="!form.menuCheckStrictly"
+            empty-text="鍔犺浇涓紝璇风◢鍊�"
+            :props="defaultProps"
+          ></el-tree>
+        </el-form-item>
+        <el-form-item label="澶囨敞">
+          <el-input v-model="form.remark" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�"></el-input>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+
+    <!-- 鍒嗛厤瑙掕壊鏁版嵁鏉冮檺瀵硅瘽妗� -->
+    <el-dialog :title="title" :visible.sync="openDataScope" width="500px" append-to-body>
+      <el-form :model="form" label-width="80px">
+        <el-form-item label="瑙掕壊鍚嶇О">
+          <el-input v-model="form.roleName" :disabled="true" />
+        </el-form-item>
+        <el-form-item label="鏉冮檺瀛楃">
+          <el-input v-model="form.roleKey" :disabled="true" />
+        </el-form-item>
+        <el-form-item label="鏉冮檺鑼冨洿">
+          <el-select v-model="form.dataScope" @change="dataScopeSelectChange">
+            <el-option
+              v-for="item in dataScopeOptions"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="鏁版嵁鏉冮檺" v-show="form.dataScope == 2">
+          <el-checkbox v-model="deptExpand" @change="handleCheckedTreeExpand($event, 'dept')">灞曞紑/鎶樺彔</el-checkbox>
+          <el-checkbox v-model="deptNodeAll" @change="handleCheckedTreeNodeAll($event, 'dept')">鍏ㄩ��/鍏ㄤ笉閫�</el-checkbox>
+          <el-checkbox v-model="form.deptCheckStrictly" @change="handleCheckedTreeConnect($event, 'dept')">鐖跺瓙鑱斿姩</el-checkbox>
+          <el-tree
+            class="tree-border"
+            :data="deptOptions"
+            show-checkbox
+            default-expand-all
+            ref="dept"
+            node-key="id"
+            :check-strictly="!form.deptCheckStrictly"
+            empty-text="鍔犺浇涓紝璇风◢鍊�"
+            :props="defaultProps"
+          ></el-tree>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitDataScope">纭� 瀹�</el-button>
+        <el-button @click="cancelDataScope">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listRole, getRole, delRole, addRole, updateRole, dataScope, changeRoleStatus, deptTreeSelect } from "@/api/system/role";
+import { treeselect as menuTreeselect, roleMenuTreeselect } from "@/api/system/menu";
+
+export default {
+  name: "Role",
+  dicts: ['sys_normal_disable'],
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 瑙掕壊琛ㄦ牸鏁版嵁
+      roleList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏄惁鏄剧ず寮瑰嚭灞傦紙鏁版嵁鏉冮檺锛�
+      openDataScope: false,
+      menuExpand: false,
+      menuNodeAll: false,
+      deptExpand: true,
+      deptNodeAll: false,
+      // 鏃ユ湡鑼冨洿
+      dateRange: [],
+      // 鏁版嵁鑼冨洿閫夐」
+      dataScopeOptions: [
+        {
+          value: "1",
+          label: "鍏ㄩ儴鏁版嵁鏉冮檺"
+        },
+        {
+          value: "2",
+          label: "鑷畾鏁版嵁鏉冮檺"
+        },
+        {
+          value: "3",
+          label: "鏈儴闂ㄦ暟鎹潈闄�"
+        },
+        {
+          value: "4",
+          label: "鏈儴闂ㄥ強浠ヤ笅鏁版嵁鏉冮檺"
+        },
+        {
+          value: "5",
+          label: "浠呮湰浜烘暟鎹潈闄�"
+        }
+      ],
+      // 鑿滃崟鍒楄〃
+      menuOptions: [],
+      // 閮ㄩ棬鍒楄〃
+      deptOptions: [],
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        roleName: undefined,
+        roleKey: undefined,
+        status: undefined
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      defaultProps: {
+        children: "children",
+        label: "label"
+      },
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        roleName: [
+          { required: true, message: "瑙掕壊鍚嶇О涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        roleKey: [
+          { required: true, message: "鏉冮檺瀛楃涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        roleSort: [
+          { required: true, message: "瑙掕壊椤哄簭涓嶈兘涓虹┖", trigger: "blur" }
+        ]
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 鏌ヨ瑙掕壊鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listRole(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
+          this.roleList = response.rows;
+          this.total = response.total;
+          this.loading = false;
+        }
+      );
+    },
+    /** 鏌ヨ鑿滃崟鏍戠粨鏋� */
+    getMenuTreeselect() {
+      menuTreeselect().then(response => {
+        this.menuOptions = response.data;
+      });
+    },
+    // 鎵�鏈夎彍鍗曡妭鐐规暟鎹�
+    getMenuAllCheckedKeys() {
+      // 鐩墠琚�変腑鐨勮彍鍗曡妭鐐�
+      let checkedKeys = this.$refs.menu.getCheckedKeys();
+      // 鍗婇�変腑鐨勮彍鍗曡妭鐐�
+      let halfCheckedKeys = this.$refs.menu.getHalfCheckedKeys();
+      checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys);
+      return checkedKeys;
+    },
+    // 鎵�鏈夐儴闂ㄨ妭鐐规暟鎹�
+    getDeptAllCheckedKeys() {
+      // 鐩墠琚�変腑鐨勯儴闂ㄨ妭鐐�
+      let checkedKeys = this.$refs.dept.getCheckedKeys();
+      // 鍗婇�変腑鐨勯儴闂ㄨ妭鐐�
+      let halfCheckedKeys = this.$refs.dept.getHalfCheckedKeys();
+      checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys);
+      return checkedKeys;
+    },
+    /** 鏍规嵁瑙掕壊ID鏌ヨ鑿滃崟鏍戠粨鏋� */
+    getRoleMenuTreeselect(roleId) {
+      return roleMenuTreeselect(roleId).then(response => {
+        this.menuOptions = response.menus;
+        return response;
+      });
+    },
+    /** 鏍规嵁瑙掕壊ID鏌ヨ閮ㄩ棬鏍戠粨鏋� */
+    getDeptTree(roleId) {
+      return deptTreeSelect(roleId).then(response => {
+        this.deptOptions = response.depts;
+        return response;
+      });
+    },
+    // 瑙掕壊鐘舵�佷慨鏀�
+    handleStatusChange(row) {
+      let text = row.status === "0" ? "鍚敤" : "鍋滅敤";
+      this.$modal.confirm('纭瑕�"' + text + '""' + row.roleName + '"瑙掕壊鍚楋紵').then(function() {
+        return changeRoleStatus(row.roleId, row.status);
+      }).then(() => {
+        this.$modal.msgSuccess(text + "鎴愬姛");
+      }).catch(function() {
+        row.status = row.status === "0" ? "1" : "0";
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 鍙栨秷鎸夐挳锛堟暟鎹潈闄愶級
+    cancelDataScope() {
+      this.openDataScope = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      if (this.$refs.menu != undefined) {
+        this.$refs.menu.setCheckedKeys([]);
+      }
+      this.menuExpand = false,
+      this.menuNodeAll = false,
+      this.deptExpand = true,
+      this.deptNodeAll = false,
+      this.form = {
+        roleId: undefined,
+        roleName: undefined,
+        roleKey: undefined,
+        roleSort: 0,
+        status: "0",
+        menuIds: [],
+        deptIds: [],
+        menuCheckStrictly: true,
+        deptCheckStrictly: true,
+        remark: undefined
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.dateRange = [];
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.roleId)
+      this.single = selection.length!=1
+      this.multiple = !selection.length
+    },
+    // 鏇村鎿嶄綔瑙﹀彂
+    handleCommand(command, row) {
+      switch (command) {
+        case "handleDataScope":
+          this.handleDataScope(row);
+          break;
+        case "handleAuthUser":
+          this.handleAuthUser(row);
+          break;
+        default:
+          break;
+      }
+    },
+    // 鏍戞潈闄愶紙灞曞紑/鎶樺彔锛�
+    handleCheckedTreeExpand(value, type) {
+      if (type == 'menu') {
+        let treeList = this.menuOptions;
+        for (let i = 0; i < treeList.length; i++) {
+          this.$refs.menu.store.nodesMap[treeList[i].id].expanded = value;
+        }
+      } else if (type == 'dept') {
+        let treeList = this.deptOptions;
+        for (let i = 0; i < treeList.length; i++) {
+          this.$refs.dept.store.nodesMap[treeList[i].id].expanded = value;
+        }
+      }
+    },
+    // 鏍戞潈闄愶紙鍏ㄩ��/鍏ㄤ笉閫夛級
+    handleCheckedTreeNodeAll(value, type) {
+      if (type == 'menu') {
+        this.$refs.menu.setCheckedNodes(value ? this.menuOptions: []);
+      } else if (type == 'dept') {
+        this.$refs.dept.setCheckedNodes(value ? this.deptOptions: []);
+      }
+    },
+    // 鏍戞潈闄愶紙鐖跺瓙鑱斿姩锛�
+    handleCheckedTreeConnect(value, type) {
+      if (type == 'menu') {
+        this.form.menuCheckStrictly = value ? true: false;
+      } else if (type == 'dept') {
+        this.form.deptCheckStrictly = value ? true: false;
+      }
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.reset();
+      this.getMenuTreeselect();
+      this.open = true;
+      this.title = "娣诲姞瑙掕壊";
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.reset();
+      const roleId = row.roleId || this.ids
+      const roleMenu = this.getRoleMenuTreeselect(roleId);
+      getRole(roleId).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.$nextTick(() => {
+          roleMenu.then(res => {
+            let checkedKeys = res.checkedKeys
+            checkedKeys.forEach((v) => {
+                this.$nextTick(()=>{
+                    this.$refs.menu.setChecked(v, true ,false);
+                })
+            })
+          });
+        });
+        this.title = "淇敼瑙掕壊";
+      });
+    },
+    /** 閫夋嫨瑙掕壊鏉冮檺鑼冨洿瑙﹀彂 */
+    dataScopeSelectChange(value) {
+      if(value !== '2') {
+        this.$refs.dept.setCheckedKeys([]);
+      }
+    },
+    /** 鍒嗛厤鏁版嵁鏉冮檺鎿嶄綔 */
+    handleDataScope(row) {
+      this.reset();
+      const deptTreeSelect = this.getDeptTree(row.roleId);
+      getRole(row.roleId).then(response => {
+        this.form = response.data;
+        this.openDataScope = true;
+        this.$nextTick(() => {
+          deptTreeSelect.then(res => {
+            this.$refs.dept.setCheckedKeys(res.checkedKeys);
+          });
+        });
+        this.title = "鍒嗛厤鏁版嵁鏉冮檺";
+      });
+    },
+    /** 鍒嗛厤鐢ㄦ埛鎿嶄綔 */
+    handleAuthUser: function(row) {
+      const roleId = row.roleId;
+      this.$router.push("/system/role-auth/user/" + roleId);
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm: function() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.roleId != undefined) {
+            this.form.menuIds = this.getMenuAllCheckedKeys();
+            updateRole(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            this.form.menuIds = this.getMenuAllCheckedKeys();
+            addRole(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鎻愪氦鎸夐挳锛堟暟鎹潈闄愶級 */
+    submitDataScope: function() {
+      if (this.form.roleId != undefined) {
+        this.form.deptIds = this.getDeptAllCheckedKeys();
+        dataScope(this.form).then(response => {
+          this.$modal.msgSuccess("淇敼鎴愬姛");
+          this.openDataScope = false;
+          this.getList();
+        });
+      }
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const roleIds = row.roleId || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎瑙掕壊缂栧彿涓�"' + roleIds + '"鐨勬暟鎹」锛�').then(function() {
+        return delRole(roleIds);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('system/role/export', {
+        ...this.queryParams
+      }, `role_${new Date().getTime()}.xlsx`)
+    }
+  }
+};
+</script>
\ No newline at end of file
diff --git a/jcdm-ui/src/views/system/role/selectUser.vue b/jcdm-ui/src/views/system/role/selectUser.vue
new file mode 100644
index 0000000..b2b072f
--- /dev/null
+++ b/jcdm-ui/src/views/system/role/selectUser.vue
@@ -0,0 +1,138 @@
+<template>
+  <!-- 鎺堟潈鐢ㄦ埛 -->
+  <el-dialog title="閫夋嫨鐢ㄦ埛" :visible.sync="visible" width="800px" top="5vh" append-to-body>
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true">
+      <el-form-item label="鐢ㄦ埛鍚嶇О" prop="userName">
+        <el-input
+          v-model="queryParams.userName"
+          placeholder="璇疯緭鍏ョ敤鎴峰悕绉�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="鎵嬫満鍙风爜" prop="phonenumber">
+        <el-input
+          v-model="queryParams.phonenumber"
+          placeholder="璇疯緭鍏ユ墜鏈哄彿鐮�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+    <el-row>
+      <el-table @row-click="clickRow" ref="table" :data="userList" @selection-change="handleSelectionChange" height="260px">
+        <el-table-column type="selection" width="55"></el-table-column>
+        <el-table-column label="鐢ㄦ埛鍚嶇О" prop="userName" :show-overflow-tooltip="true" />
+        <el-table-column label="鐢ㄦ埛鏄电О" prop="nickName" :show-overflow-tooltip="true" />
+        <el-table-column label="閭" prop="email" :show-overflow-tooltip="true" />
+        <el-table-column label="鎵嬫満" prop="phonenumber" :show-overflow-tooltip="true" />
+        <el-table-column label="鐘舵��" align="center" prop="status">
+          <template slot-scope="scope">
+            <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
+          </template>
+        </el-table-column>
+        <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180">
+          <template slot-scope="scope">
+            <span>{{ parseTime(scope.row.createTime) }}</span>
+          </template>
+        </el-table-column>
+      </el-table>
+      <pagination
+        v-show="total>0"
+        :total="total"
+        :page.sync="queryParams.pageNum"
+        :limit.sync="queryParams.pageSize"
+        @pagination="getList"
+      />
+    </el-row>
+    <div slot="footer" class="dialog-footer">
+      <el-button type="primary" @click="handleSelectUser">纭� 瀹�</el-button>
+      <el-button @click="visible = false">鍙� 娑�</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { unallocatedUserList, authUserSelectAll } from "@/api/system/role";
+export default {
+  dicts: ['sys_normal_disable'],
+  props: {
+    // 瑙掕壊缂栧彿
+    roleId: {
+      type: [Number, String]
+    }
+  },
+  data() {
+    return {
+      // 閬僵灞�
+      visible: false,
+      // 閫変腑鏁扮粍鍊�
+      userIds: [],
+      // 鎬绘潯鏁�
+      total: 0,
+      // 鏈巿鏉冪敤鎴锋暟鎹�
+      userList: [],
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        roleId: undefined,
+        userName: undefined,
+        phonenumber: undefined
+      }
+    };
+  },
+  methods: {
+    // 鏄剧ず寮规
+    show() {
+      this.queryParams.roleId = this.roleId;
+      this.getList();
+      this.visible = true;
+    },
+    clickRow(row) {
+      this.$refs.table.toggleRowSelection(row);
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.userIds = selection.map(item => item.userId);
+    },
+    // 鏌ヨ琛ㄦ暟鎹�
+    getList() {
+      unallocatedUserList(this.queryParams).then(res => {
+        this.userList = res.rows;
+        this.total = res.total;
+      });
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    /** 閫夋嫨鎺堟潈鐢ㄦ埛鎿嶄綔 */
+    handleSelectUser() {
+      const roleId = this.queryParams.roleId;
+      const userIds = this.userIds.join(",");
+      if (userIds == "") {
+        this.$modal.msgError("璇烽�夋嫨瑕佸垎閰嶇殑鐢ㄦ埛");
+        return;
+      }
+      authUserSelectAll({ roleId: roleId, userIds: userIds }).then(res => {
+        this.$modal.msgSuccess(res.msg);
+        if (res.code === 200) {
+          this.visible = false;
+          this.$emit("ok");
+        }
+      });
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/system/user/authRole.vue b/jcdm-ui/src/views/system/user/authRole.vue
new file mode 100644
index 0000000..943710e
--- /dev/null
+++ b/jcdm-ui/src/views/system/user/authRole.vue
@@ -0,0 +1,117 @@
+<template>
+  <div class="app-container">
+    <h4 class="form-header h4">鍩烘湰淇℃伅</h4>
+    <el-form ref="form" :model="form" label-width="80px">
+      <el-row>
+        <el-col :span="8" :offset="2">
+          <el-form-item label="鐢ㄦ埛鏄电О" prop="nickName">
+            <el-input v-model="form.nickName" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col :span="8" :offset="2">
+          <el-form-item label="鐧诲綍璐﹀彿" prop="userName">
+            <el-input  v-model="form.userName" disabled />
+          </el-form-item>
+        </el-col>
+      </el-row>
+    </el-form>
+
+    <h4 class="form-header h4">瑙掕壊淇℃伅</h4>
+    <el-table v-loading="loading" :row-key="getRowKey" @row-click="clickRow" ref="table" @selection-change="handleSelectionChange" :data="roles.slice((pageNum-1)*pageSize,pageNum*pageSize)">
+      <el-table-column label="搴忓彿" type="index" align="center">
+        <template slot-scope="scope">
+          <span>{{(pageNum - 1) * pageSize + scope.$index + 1}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column type="selection" :reserve-selection="true" width="55"></el-table-column>
+      <el-table-column label="瑙掕壊缂栧彿" align="center" prop="roleId" />
+      <el-table-column label="瑙掕壊鍚嶇О" align="center" prop="roleName" />
+      <el-table-column label="鏉冮檺瀛楃" align="center" prop="roleKey" />
+      <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination v-show="total>0" :total="total" :page.sync="pageNum" :limit.sync="pageSize" />
+
+    <el-form label-width="100px">
+      <el-form-item style="text-align: center;margin-left:-120px;margin-top:30px;">
+        <el-button type="primary" @click="submitForm()">鎻愪氦</el-button>
+        <el-button @click="close()">杩斿洖</el-button>
+      </el-form-item>
+    </el-form>
+  </div>
+</template>
+
+<script>
+import { getAuthRole, updateAuthRole } from "@/api/system/user";
+
+export default {
+  name: "AuthRole",
+  data() {
+    return {
+       // 閬僵灞�
+      loading: true,
+      // 鍒嗛〉淇℃伅
+      total: 0,
+      pageNum: 1,
+      pageSize: 10,
+      // 閫変腑瑙掕壊缂栧彿
+      roleIds:[],
+      // 瑙掕壊淇℃伅
+      roles: [],
+      // 鐢ㄦ埛淇℃伅
+      form: {}
+    };
+  },
+  created() {
+    const userId = this.$route.params && this.$route.params.userId;
+    if (userId) {
+      this.loading = true;
+      getAuthRole(userId).then((response) => {
+        this.form = response.user;
+        this.roles = response.roles;
+        this.total = this.roles.length;
+        this.$nextTick(() => {
+          this.roles.forEach((row) => {
+            if (row.flag) {
+              this.$refs.table.toggleRowSelection(row);
+            }
+          });
+        });
+        this.loading = false;
+      });
+    }
+  },
+  methods: {
+    /** 鍗曞嚮閫変腑琛屾暟鎹� */
+    clickRow(row) {
+      this.$refs.table.toggleRowSelection(row);
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.roleIds = selection.map((item) => item.roleId);
+    },
+    // 淇濆瓨閫変腑鐨勬暟鎹紪鍙�
+    getRowKey(row) {
+      return row.roleId;
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm() {
+      const userId = this.form.userId;
+      const roleIds = this.roleIds.join(",");
+      updateAuthRole({ userId: userId, roleIds: roleIds }).then((response) => {
+        this.$modal.msgSuccess("鎺堟潈鎴愬姛");
+        this.close();
+      });
+    },
+    /** 鍏抽棴鎸夐挳 */
+    close() {
+      const obj = { path: "/system/user" };
+      this.$tab.closeOpenPage(obj);
+    },
+  },
+};
+</script>
\ No newline at end of file
diff --git a/jcdm-ui/src/views/system/user/index.vue b/jcdm-ui/src/views/system/user/index.vue
new file mode 100644
index 0000000..ae87fe4
--- /dev/null
+++ b/jcdm-ui/src/views/system/user/index.vue
@@ -0,0 +1,670 @@
+<template>
+  <div class="app-container">
+    <el-row :gutter="20">
+      <!--閮ㄩ棬鏁版嵁-->
+      <el-col :span="4" :xs="24">
+        <div class="head-container">
+          <el-input
+            v-model="deptName"
+            placeholder="璇疯緭鍏ラ儴闂ㄥ悕绉�"
+            clearable
+            size="small"
+            prefix-icon="el-icon-search"
+            style="margin-bottom: 20px"
+          />
+        </div>
+        <div class="head-container">
+          <el-tree
+            :data="deptOptions"
+            :props="defaultProps"
+            :expand-on-click-node="false"
+            :filter-node-method="filterNode"
+            ref="tree"
+            node-key="id"
+            default-expand-all
+            highlight-current
+            @node-click="handleNodeClick"
+          />
+        </div>
+      </el-col>
+      <!--鐢ㄦ埛鏁版嵁-->
+      <el-col :span="20" :xs="24">
+        <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+          <el-form-item label="鐢ㄦ埛鍚嶇О" prop="userName">
+            <el-input
+              v-model="queryParams.userName"
+              placeholder="璇疯緭鍏ョ敤鎴峰悕绉�"
+              clearable
+              style="width: 240px"
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item label="鎵嬫満鍙风爜" prop="phonenumber">
+            <el-input
+              v-model="queryParams.phonenumber"
+              placeholder="璇疯緭鍏ユ墜鏈哄彿鐮�"
+              clearable
+              style="width: 240px"
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item label="鐘舵��" prop="status">
+            <el-select
+              v-model="queryParams.status"
+              placeholder="鐢ㄦ埛鐘舵��"
+              clearable
+              style="width: 240px"
+            >
+              <el-option
+                v-for="dict in dict.type.sys_normal_disable"
+                :key="dict.value"
+                :label="dict.label"
+                :value="dict.value"
+              />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="鍒涘缓鏃堕棿">
+            <el-date-picker
+              v-model="dateRange"
+              style="width: 240px"
+              value-format="yyyy-MM-dd"
+              type="daterange"
+              range-separator="-"
+              start-placeholder="寮�濮嬫棩鏈�"
+              end-placeholder="缁撴潫鏃ユ湡"
+            ></el-date-picker>
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+            <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+          </el-form-item>
+        </el-form>
+
+        <el-row :gutter="10" class="mb8">
+          <el-col :span="1.5">
+            <el-button
+              type="primary"
+              plain
+              icon="el-icon-plus"
+              size="mini"
+              @click="handleAdd"
+              v-hasPermi="['system:user:add']"
+            >鏂板</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="success"
+              plain
+              icon="el-icon-edit"
+              size="mini"
+              :disabled="single"
+              @click="handleUpdate"
+              v-hasPermi="['system:user:edit']"
+            >淇敼</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="danger"
+              plain
+              icon="el-icon-delete"
+              size="mini"
+              :disabled="multiple"
+              @click="handleDelete"
+              v-hasPermi="['system:user:remove']"
+            >鍒犻櫎</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="info"
+              plain
+              icon="el-icon-upload2"
+              size="mini"
+              @click="handleImport"
+              v-hasPermi="['system:user:import']"
+            >瀵煎叆</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="warning"
+              plain
+              icon="el-icon-download"
+              size="mini"
+              @click="handleExport"
+              v-hasPermi="['system:user:export']"
+            >瀵煎嚭</el-button>
+          </el-col>
+          <right-toolbar :showSearch.sync="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
+        </el-row>
+
+        <el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
+          <el-table-column type="selection" width="50" align="center" />
+          <el-table-column label="鐢ㄦ埛缂栧彿" align="center" key="userId" prop="userId" v-if="columns[0].visible" />
+          <el-table-column label="鐢ㄦ埛鍚嶇О" align="center" key="userName" prop="userName" v-if="columns[1].visible" :show-overflow-tooltip="true" />
+          <el-table-column label="鐢ㄦ埛鏄电О" align="center" key="nickName" prop="nickName" v-if="columns[2].visible" :show-overflow-tooltip="true" />
+          <el-table-column label="閮ㄩ棬" align="center" key="deptName" prop="dept.deptName" v-if="columns[3].visible" :show-overflow-tooltip="true" />
+          <el-table-column label="鎵嬫満鍙风爜" align="center" key="phonenumber" prop="phonenumber" v-if="columns[4].visible" width="120" />
+          <el-table-column label="鐘舵��" align="center" key="status" v-if="columns[5].visible">
+            <template slot-scope="scope">
+              <el-switch
+                v-model="scope.row.status"
+                active-value="0"
+                inactive-value="1"
+                @change="handleStatusChange(scope.row)"
+              ></el-switch>
+            </template>
+          </el-table-column>
+          <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" v-if="columns[6].visible" width="160">
+            <template slot-scope="scope">
+              <span>{{ parseTime(scope.row.createTime) }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column
+            label="鎿嶄綔"
+            align="center"
+            width="160"
+            class-name="small-padding fixed-width"
+          >
+            <template slot-scope="scope" v-if="scope.row.userId !== 1">
+              <el-button
+                size="mini"
+                type="text"
+                icon="el-icon-edit"
+                @click="handleUpdate(scope.row)"
+                v-hasPermi="['system:user:edit']"
+              >淇敼</el-button>
+              <el-button
+                size="mini"
+                type="text"
+                icon="el-icon-delete"
+                @click="handleDelete(scope.row)"
+                v-hasPermi="['system:user:remove']"
+              >鍒犻櫎</el-button>
+              <el-dropdown size="mini" @command="(command) => handleCommand(command, scope.row)" v-hasPermi="['system:user:resetPwd', 'system:user:edit']">
+                <el-button size="mini" type="text" icon="el-icon-d-arrow-right">鏇村</el-button>
+                <el-dropdown-menu slot="dropdown">
+                  <el-dropdown-item command="handleResetPwd" icon="el-icon-key"
+                    v-hasPermi="['system:user:resetPwd']">閲嶇疆瀵嗙爜</el-dropdown-item>
+                  <el-dropdown-item command="handleAuthRole" icon="el-icon-circle-check"
+                    v-hasPermi="['system:user:edit']">鍒嗛厤瑙掕壊</el-dropdown-item>
+                </el-dropdown-menu>
+              </el-dropdown>
+            </template>
+          </el-table-column>
+        </el-table>
+
+        <pagination
+          v-show="total>0"
+          :total="total"
+          :page.sync="queryParams.pageNum"
+          :limit.sync="queryParams.pageSize"
+          @pagination="getList"
+        />
+      </el-col>
+    </el-row>
+
+    <!-- 娣诲姞鎴栦慨鏀圭敤鎴烽厤缃璇濇 -->
+    <el-dialog :title="title" :visible.sync="open" width="600px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="鐢ㄦ埛鏄电О" prop="nickName">
+              <el-input v-model="form.nickName" placeholder="璇疯緭鍏ョ敤鎴锋樀绉�" maxlength="30" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="褰掑睘閮ㄩ棬" prop="deptId">
+              <treeselect v-model="form.deptId" :options="deptOptions" :show-count="true" placeholder="璇烽�夋嫨褰掑睘閮ㄩ棬" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="鎵嬫満鍙风爜" prop="phonenumber">
+              <el-input v-model="form.phonenumber" placeholder="璇疯緭鍏ユ墜鏈哄彿鐮�" maxlength="11" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="閭" prop="email">
+              <el-input v-model="form.email" placeholder="璇疯緭鍏ラ偖绠�" maxlength="50" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item v-if="form.userId == undefined" label="鐢ㄦ埛鍚嶇О" prop="userName">
+              <el-input v-model="form.userName" placeholder="璇疯緭鍏ョ敤鎴峰悕绉�" maxlength="30" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item v-if="form.userId == undefined" label="鐢ㄦ埛瀵嗙爜" prop="password">
+              <el-input v-model="form.password" placeholder="璇疯緭鍏ョ敤鎴峰瘑鐮�" type="password" maxlength="20" show-password/>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="鐢ㄦ埛鎬у埆">
+              <el-select v-model="form.sex" placeholder="璇烽�夋嫨鎬у埆">
+                <el-option
+                  v-for="dict in dict.type.sys_user_sex"
+                  :key="dict.value"
+                  :label="dict.label"
+                  :value="dict.value"
+                ></el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鐘舵��">
+              <el-radio-group v-model="form.status">
+                <el-radio
+                  v-for="dict in dict.type.sys_normal_disable"
+                  :key="dict.value"
+                  :label="dict.value"
+                >{{dict.label}}</el-radio>
+              </el-radio-group>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="宀椾綅">
+              <el-select v-model="form.postIds" multiple placeholder="璇烽�夋嫨宀椾綅">
+                <el-option
+                  v-for="item in postOptions"
+                  :key="item.postId"
+                  :label="item.postName"
+                  :value="item.postId"
+                  :disabled="item.status == 1"
+                ></el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="瑙掕壊">
+              <el-select v-model="form.roleIds" multiple placeholder="璇烽�夋嫨瑙掕壊">
+                <el-option
+                  v-for="item in roleOptions"
+                  :key="item.roleId"
+                  :label="item.roleName"
+                  :value="item.roleId"
+                  :disabled="item.status == 1"
+                ></el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="24">
+            <el-form-item label="澶囨敞">
+              <el-input v-model="form.remark" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�"></el-input>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+
+    <!-- 鐢ㄦ埛瀵煎叆瀵硅瘽妗� -->
+    <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
+      <el-upload
+        ref="upload"
+        :limit="1"
+        accept=".xlsx, .xls"
+        :headers="upload.headers"
+        :action="upload.url + '?updateSupport=' + upload.updateSupport"
+        :disabled="upload.isUploading"
+        :on-progress="handleFileUploadProgress"
+        :on-success="handleFileSuccess"
+        :auto-upload="false"
+        drag
+      >
+        <i class="el-icon-upload"></i>
+        <div class="el-upload__text">灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em></div>
+        <div class="el-upload__tip text-center" slot="tip">
+          <div class="el-upload__tip" slot="tip">
+            <el-checkbox v-model="upload.updateSupport" /> 鏄惁鏇存柊宸茬粡瀛樺湪鐨勭敤鎴锋暟鎹�
+          </div>
+          <span>浠呭厑璁稿鍏ls銆亁lsx鏍煎紡鏂囦欢銆�</span>
+          <el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;" @click="importTemplate">涓嬭浇妯℃澘</el-link>
+        </div>
+      </el-upload>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitFileForm">纭� 瀹�</el-button>
+        <el-button @click="upload.open = false">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listUser, getUser, delUser, addUser, updateUser, resetUserPwd, changeUserStatus, deptTreeSelect } from "@/api/system/user";
+import { getToken } from "@/utils/auth";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+
+export default {
+  name: "User",
+  dicts: ['sys_normal_disable', 'sys_user_sex'],
+  components: { Treeselect },
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 鐢ㄦ埛琛ㄦ牸鏁版嵁
+      userList: null,
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 閮ㄩ棬鏍戦�夐」
+      deptOptions: undefined,
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 閮ㄩ棬鍚嶇О
+      deptName: undefined,
+      // 榛樿瀵嗙爜
+      initPassword: undefined,
+      // 鏃ユ湡鑼冨洿
+      dateRange: [],
+      // 宀椾綅閫夐」
+      postOptions: [],
+      // 瑙掕壊閫夐」
+      roleOptions: [],
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      defaultProps: {
+        children: "children",
+        label: "label"
+      },
+      // 鐢ㄦ埛瀵煎叆鍙傛暟
+      upload: {
+        // 鏄惁鏄剧ず寮瑰嚭灞傦紙鐢ㄦ埛瀵煎叆锛�
+        open: false,
+        // 寮瑰嚭灞傛爣棰橈紙鐢ㄦ埛瀵煎叆锛�
+        title: "",
+        // 鏄惁绂佺敤涓婁紶
+        isUploading: false,
+        // 鏄惁鏇存柊宸茬粡瀛樺湪鐨勭敤鎴锋暟鎹�
+        updateSupport: 0,
+        // 璁剧疆涓婁紶鐨勮姹傚ご閮�
+        headers: { Authorization: "Bearer " + getToken() },
+        // 涓婁紶鐨勫湴鍧�
+        url: process.env.VUE_APP_BASE_API + "/system/user/importData"
+      },
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        userName: undefined,
+        phonenumber: undefined,
+        status: undefined,
+        deptId: undefined
+      },
+      // 鍒椾俊鎭�
+      columns: [
+        { key: 0, label: `鐢ㄦ埛缂栧彿`, visible: true },
+        { key: 1, label: `鐢ㄦ埛鍚嶇О`, visible: true },
+        { key: 2, label: `鐢ㄦ埛鏄电О`, visible: true },
+        { key: 3, label: `閮ㄩ棬`, visible: true },
+        { key: 4, label: `鎵嬫満鍙风爜`, visible: true },
+        { key: 5, label: `鐘舵�乣, visible: true },
+        { key: 6, label: `鍒涘缓鏃堕棿`, visible: true }
+      ],
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        userName: [
+          { required: true, message: "鐢ㄦ埛鍚嶇О涓嶈兘涓虹┖", trigger: "blur" },
+          { min: 2, max: 20, message: '鐢ㄦ埛鍚嶇О闀垮害蹇呴』浠嬩簬 2 鍜� 20 涔嬮棿', trigger: 'blur' }
+        ],
+        nickName: [
+          { required: true, message: "鐢ㄦ埛鏄电О涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        password: [
+          { required: true, message: "鐢ㄦ埛瀵嗙爜涓嶈兘涓虹┖", trigger: "blur" },
+          { min: 5, max: 20, message: '鐢ㄦ埛瀵嗙爜闀垮害蹇呴』浠嬩簬 5 鍜� 20 涔嬮棿', trigger: 'blur' }
+        ],
+        email: [
+          {
+            type: "email",
+            message: "璇疯緭鍏ユ纭殑閭鍦板潃",
+            trigger: ["blur", "change"]
+          }
+        ],
+        phonenumber: [
+          {
+            pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
+            message: "璇疯緭鍏ユ纭殑鎵嬫満鍙风爜",
+            trigger: "blur"
+          }
+        ]
+      }
+    };
+  },
+  watch: {
+    // 鏍规嵁鍚嶇О绛涢�夐儴闂ㄦ爲
+    deptName(val) {
+      this.$refs.tree.filter(val);
+    }
+  },
+  created() {
+    this.getList();
+    this.getDeptTree();
+    this.getConfigKey("sys.user.initPassword").then(response => {
+      this.initPassword = response.msg;
+    });
+  },
+  methods: {
+    /** 鏌ヨ鐢ㄦ埛鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listUser(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
+          this.userList = response.rows;
+          this.total = response.total;
+          this.loading = false;
+        }
+      );
+    },
+    /** 鏌ヨ閮ㄩ棬涓嬫媺鏍戠粨鏋� */
+    getDeptTree() {
+      deptTreeSelect().then(response => {
+        this.deptOptions = response.data;
+      });
+    },
+    // 绛涢�夎妭鐐�
+    filterNode(value, data) {
+      if (!value) return true;
+      return data.label.indexOf(value) !== -1;
+    },
+    // 鑺傜偣鍗曞嚮浜嬩欢
+    handleNodeClick(data) {
+      this.queryParams.deptId = data.id;
+      this.handleQuery();
+    },
+    // 鐢ㄦ埛鐘舵�佷慨鏀�
+    handleStatusChange(row) {
+      let text = row.status === "0" ? "鍚敤" : "鍋滅敤";
+      this.$modal.confirm('纭瑕�"' + text + '""' + row.userName + '"鐢ㄦ埛鍚楋紵').then(function() {
+        return changeUserStatus(row.userId, row.status);
+      }).then(() => {
+        this.$modal.msgSuccess(text + "鎴愬姛");
+      }).catch(function() {
+        row.status = row.status === "0" ? "1" : "0";
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        userId: undefined,
+        deptId: undefined,
+        userName: undefined,
+        nickName: undefined,
+        password: undefined,
+        phonenumber: undefined,
+        email: undefined,
+        sex: undefined,
+        status: "0",
+        remark: undefined,
+        postIds: [],
+        roleIds: []
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.dateRange = [];
+      this.resetForm("queryForm");
+      this.queryParams.deptId = undefined;
+      this.$refs.tree.setCurrentKey(null);
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.userId);
+      this.single = selection.length != 1;
+      this.multiple = !selection.length;
+    },
+    // 鏇村鎿嶄綔瑙﹀彂
+    handleCommand(command, row) {
+      switch (command) {
+        case "handleResetPwd":
+          this.handleResetPwd(row);
+          break;
+        case "handleAuthRole":
+          this.handleAuthRole(row);
+          break;
+        default:
+          break;
+      }
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.reset();
+      getUser().then(response => {
+        this.postOptions = response.posts;
+        this.roleOptions = response.roles;
+        this.open = true;
+        this.title = "娣诲姞鐢ㄦ埛";
+        this.form.password = this.initPassword;
+      });
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.reset();
+      const userId = row.userId || this.ids;
+      getUser(userId).then(response => {
+        this.form = response.data;
+        this.postOptions = response.posts;
+        this.roleOptions = response.roles;
+        this.$set(this.form, "postIds", response.postIds);
+        this.$set(this.form, "roleIds", response.roleIds);
+        this.open = true;
+        this.title = "淇敼鐢ㄦ埛";
+        this.form.password = "";
+      });
+    },
+    /** 閲嶇疆瀵嗙爜鎸夐挳鎿嶄綔 */
+    handleResetPwd(row) {
+      this.$prompt('璇疯緭鍏�"' + row.userName + '"鐨勬柊瀵嗙爜', "鎻愮ず", {
+        confirmButtonText: "纭畾",
+        cancelButtonText: "鍙栨秷",
+        closeOnClickModal: false,
+        inputPattern: /^.{5,20}$/,
+        inputErrorMessage: "鐢ㄦ埛瀵嗙爜闀垮害蹇呴』浠嬩簬 5 鍜� 20 涔嬮棿"
+      }).then(({ value }) => {
+          resetUserPwd(row.userId, value).then(response => {
+            this.$modal.msgSuccess("淇敼鎴愬姛锛屾柊瀵嗙爜鏄細" + value);
+          });
+        }).catch(() => {});
+    },
+    /** 鍒嗛厤瑙掕壊鎿嶄綔 */
+    handleAuthRole: function(row) {
+      const userId = row.userId;
+      this.$router.push("/system/user-auth/role/" + userId);
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm: function() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.userId != undefined) {
+            updateUser(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addUser(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const userIds = row.userId || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎鐢ㄦ埛缂栧彿涓�"' + userIds + '"鐨勬暟鎹」锛�').then(function() {
+        return delUser(userIds);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('system/user/export', {
+        ...this.queryParams
+      }, `user_${new Date().getTime()}.xlsx`)
+    },
+    /** 瀵煎叆鎸夐挳鎿嶄綔 */
+    handleImport() {
+      this.upload.title = "鐢ㄦ埛瀵煎叆";
+      this.upload.open = true;
+    },
+    /** 涓嬭浇妯℃澘鎿嶄綔 */
+    importTemplate() {
+      this.download('system/user/importTemplate', {
+      }, `user_template_${new Date().getTime()}.xlsx`)
+    },
+    // 鏂囦欢涓婁紶涓鐞�
+    handleFileUploadProgress(event, file, fileList) {
+      this.upload.isUploading = true;
+    },
+    // 鏂囦欢涓婁紶鎴愬姛澶勭悊
+    handleFileSuccess(response, file, fileList) {
+      this.upload.open = false;
+      this.upload.isUploading = false;
+      this.$refs.upload.clearFiles();
+      this.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "瀵煎叆缁撴灉", { dangerouslyUseHTMLString: true });
+      this.getList();
+    },
+    // 鎻愪氦涓婁紶鏂囦欢
+    submitFileForm() {
+      this.$refs.upload.submit();
+    }
+  }
+};
+</script>
\ No newline at end of file
diff --git a/jcdm-ui/src/views/system/user/profile/index.vue b/jcdm-ui/src/views/system/user/profile/index.vue
new file mode 100644
index 0000000..529c564
--- /dev/null
+++ b/jcdm-ui/src/views/system/user/profile/index.vue
@@ -0,0 +1,91 @@
+<template>
+  <div class="app-container">
+    <el-row :gutter="20">
+      <el-col :span="6" :xs="24">
+        <el-card class="box-card">
+          <div slot="header" class="clearfix">
+            <span>涓汉淇℃伅</span>
+          </div>
+          <div>
+            <div class="text-center">
+              <userAvatar />
+            </div>
+            <ul class="list-group list-group-striped">
+              <li class="list-group-item">
+                <svg-icon icon-class="user" />鐢ㄦ埛鍚嶇О
+                <div class="pull-right">{{ user.userName }}</div>
+              </li>
+              <li class="list-group-item">
+                <svg-icon icon-class="phone" />鎵嬫満鍙风爜
+                <div class="pull-right">{{ user.phonenumber }}</div>
+              </li>
+              <li class="list-group-item">
+                <svg-icon icon-class="email" />鐢ㄦ埛閭
+                <div class="pull-right">{{ user.email }}</div>
+              </li>
+              <li class="list-group-item">
+                <svg-icon icon-class="tree" />鎵�灞為儴闂�
+                <div class="pull-right" v-if="user.dept">{{ user.dept.deptName }} / {{ postGroup }}</div>
+              </li>
+              <li class="list-group-item">
+                <svg-icon icon-class="peoples" />鎵�灞炶鑹�
+                <div class="pull-right">{{ roleGroup }}</div>
+              </li>
+              <li class="list-group-item">
+                <svg-icon icon-class="date" />鍒涘缓鏃ユ湡
+                <div class="pull-right">{{ user.createTime }}</div>
+              </li>
+            </ul>
+          </div>
+        </el-card>
+      </el-col>
+      <el-col :span="18" :xs="24">
+        <el-card>
+          <div slot="header" class="clearfix">
+            <span>鍩烘湰璧勬枡</span>
+          </div>
+          <el-tabs v-model="activeTab">
+            <el-tab-pane label="鍩烘湰璧勬枡" name="userinfo">
+              <userInfo :user="user" />
+            </el-tab-pane>
+            <el-tab-pane label="淇敼瀵嗙爜" name="resetPwd">
+              <resetPwd />
+            </el-tab-pane>
+          </el-tabs>
+        </el-card>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import userAvatar from "./userAvatar";
+import userInfo from "./userInfo";
+import resetPwd from "./resetPwd";
+import { getUserProfile } from "@/api/system/user";
+
+export default {
+  name: "Profile",
+  components: { userAvatar, userInfo, resetPwd },
+  data() {
+    return {
+      user: {},
+      roleGroup: {},
+      postGroup: {},
+      activeTab: "userinfo"
+    };
+  },
+  created() {
+    this.getUser();
+  },
+  methods: {
+    getUser() {
+      getUserProfile().then(response => {
+        this.user = response.data;
+        this.roleGroup = response.roleGroup;
+        this.postGroup = response.postGroup;
+      });
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/system/user/profile/resetPwd.vue b/jcdm-ui/src/views/system/user/profile/resetPwd.vue
new file mode 100644
index 0000000..64e8f8c
--- /dev/null
+++ b/jcdm-ui/src/views/system/user/profile/resetPwd.vue
@@ -0,0 +1,68 @@
+<template>
+  <el-form ref="form" :model="user" :rules="rules" label-width="80px">
+    <el-form-item label="鏃у瘑鐮�" prop="oldPassword">
+      <el-input v-model="user.oldPassword" placeholder="璇疯緭鍏ユ棫瀵嗙爜" type="password" show-password/>
+    </el-form-item>
+    <el-form-item label="鏂板瘑鐮�" prop="newPassword">
+      <el-input v-model="user.newPassword" placeholder="璇疯緭鍏ユ柊瀵嗙爜" type="password" show-password/>
+    </el-form-item>
+    <el-form-item label="纭瀵嗙爜" prop="confirmPassword">
+      <el-input v-model="user.confirmPassword" placeholder="璇风‘璁ゆ柊瀵嗙爜" type="password" show-password/>
+    </el-form-item>
+    <el-form-item>
+      <el-button type="primary" size="mini" @click="submit">淇濆瓨</el-button>
+      <el-button type="danger" size="mini" @click="close">鍏抽棴</el-button>
+    </el-form-item>
+  </el-form>
+</template>
+
+<script>
+import { updateUserPwd } from "@/api/system/user";
+
+export default {
+  data() {
+    const equalToPassword = (rule, value, callback) => {
+      if (this.user.newPassword !== value) {
+        callback(new Error("涓ゆ杈撳叆鐨勫瘑鐮佷笉涓�鑷�"));
+      } else {
+        callback();
+      }
+    };
+    return {
+      user: {
+        oldPassword: undefined,
+        newPassword: undefined,
+        confirmPassword: undefined
+      },
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        oldPassword: [
+          { required: true, message: "鏃у瘑鐮佷笉鑳戒负绌�", trigger: "blur" }
+        ],
+        newPassword: [
+          { required: true, message: "鏂板瘑鐮佷笉鑳戒负绌�", trigger: "blur" },
+          { min: 6, max: 20, message: "闀垮害鍦� 6 鍒� 20 涓瓧绗�", trigger: "blur" }
+        ],
+        confirmPassword: [
+          { required: true, message: "纭瀵嗙爜涓嶈兘涓虹┖", trigger: "blur" },
+          { required: true, validator: equalToPassword, trigger: "blur" }
+        ]
+      }
+    };
+  },
+  methods: {
+    submit() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          updateUserPwd(this.user.oldPassword, this.user.newPassword).then(response => {
+            this.$modal.msgSuccess("淇敼鎴愬姛");
+          });
+        }
+      });
+    },
+    close() {
+      this.$tab.closePage();
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/system/user/profile/userAvatar.vue b/jcdm-ui/src/views/system/user/profile/userAvatar.vue
new file mode 100644
index 0000000..cbf3ca1
--- /dev/null
+++ b/jcdm-ui/src/views/system/user/profile/userAvatar.vue
@@ -0,0 +1,184 @@
+<template>
+  <div>
+    <div class="user-info-head" @click="editCropper()"><img v-bind:src="options.img" title="鐐瑰嚮涓婁紶澶村儚" class="img-circle img-lg" /></div>
+    <el-dialog :title="title" :visible.sync="open" width="800px" append-to-body @opened="modalOpened"  @close="closeDialog">
+      <el-row>
+        <el-col :xs="24" :md="12" :style="{height: '350px'}">
+          <vue-cropper
+            ref="cropper"
+            :img="options.img"
+            :info="true"
+            :autoCrop="options.autoCrop"
+            :autoCropWidth="options.autoCropWidth"
+            :autoCropHeight="options.autoCropHeight"
+            :fixedBox="options.fixedBox"
+            :outputType="options.outputType"
+            @realTime="realTime"
+            v-if="visible"
+          />
+        </el-col>
+        <el-col :xs="24" :md="12" :style="{height: '350px'}">
+          <div class="avatar-upload-preview">
+            <img :src="previews.url" :style="previews.img" />
+          </div>
+        </el-col>
+      </el-row>
+      <br />
+      <el-row>
+        <el-col :lg="2" :sm="3" :xs="3">
+          <el-upload action="#" :http-request="requestUpload" :show-file-list="false" :before-upload="beforeUpload">
+            <el-button size="small">
+              閫夋嫨
+              <i class="el-icon-upload el-icon--right"></i>
+            </el-button>
+          </el-upload>
+        </el-col>
+        <el-col :lg="{span: 1, offset: 2}" :sm="2" :xs="2">
+          <el-button icon="el-icon-plus" size="small" @click="changeScale(1)"></el-button>
+        </el-col>
+        <el-col :lg="{span: 1, offset: 1}" :sm="2" :xs="2">
+          <el-button icon="el-icon-minus" size="small" @click="changeScale(-1)"></el-button>
+        </el-col>
+        <el-col :lg="{span: 1, offset: 1}" :sm="2" :xs="2">
+          <el-button icon="el-icon-refresh-left" size="small" @click="rotateLeft()"></el-button>
+        </el-col>
+        <el-col :lg="{span: 1, offset: 1}" :sm="2" :xs="2">
+          <el-button icon="el-icon-refresh-right" size="small" @click="rotateRight()"></el-button>
+        </el-col>
+        <el-col :lg="{span: 2, offset: 6}" :sm="2" :xs="2">
+          <el-button type="primary" size="small" @click="uploadImg()">鎻� 浜�</el-button>
+        </el-col>
+      </el-row>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import store from "@/store";
+import { VueCropper } from "vue-cropper";
+import { uploadAvatar } from "@/api/system/user";
+import { debounce } from '@/utils'
+
+export default {
+  components: { VueCropper },
+  data() {
+    return {
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏄惁鏄剧ずcropper
+      visible: false,
+      // 寮瑰嚭灞傛爣棰�
+      title: "淇敼澶村儚",
+      options: {
+        img: store.getters.avatar,  //瑁佸壀鍥剧墖鐨勫湴鍧�
+        autoCrop: true,             // 鏄惁榛樿鐢熸垚鎴浘妗�
+        autoCropWidth: 200,         // 榛樿鐢熸垚鎴浘妗嗗搴�
+        autoCropHeight: 200,        // 榛樿鐢熸垚鎴浘妗嗛珮搴�
+        fixedBox: true,             // 鍥哄畾鎴浘妗嗗ぇ灏� 涓嶅厑璁告敼鍙�
+        outputType:"png",           // 榛樿鐢熸垚鎴浘涓篜NG鏍煎紡
+        filename: 'avatar'          // 鏂囦欢鍚嶇О
+      },
+      previews: {},
+      resizeHandler: null
+    };
+  },
+  methods: {
+    // 缂栬緫澶村儚
+    editCropper() {
+      this.open = true;
+    },
+    // 鎵撳紑寮瑰嚭灞傜粨鏉熸椂鐨勫洖璋�
+    modalOpened() {
+      this.visible = true;
+      if (!this.resizeHandler) {
+        this.resizeHandler = debounce(() => {
+          this.refresh()
+        }, 100)
+      }
+      window.addEventListener("resize", this.resizeHandler)
+    },
+    // 鍒锋柊缁勪欢
+    refresh() {
+      this.$refs.cropper.refresh();
+    },
+    // 瑕嗙洊榛樿鐨勪笂浼犺涓�
+    requestUpload() {
+    },
+    // 鍚戝乏鏃嬭浆
+    rotateLeft() {
+      this.$refs.cropper.rotateLeft();
+    },
+    // 鍚戝彸鏃嬭浆
+    rotateRight() {
+      this.$refs.cropper.rotateRight();
+    },
+    // 鍥剧墖缂╂斁
+    changeScale(num) {
+      num = num || 1;
+      this.$refs.cropper.changeScale(num);
+    },
+    // 涓婁紶棰勫鐞�
+    beforeUpload(file) {
+      if (file.type.indexOf("image/") == -1) {
+        this.$modal.msgError("鏂囦欢鏍煎紡閿欒锛岃涓婁紶鍥剧墖绫诲瀷,濡傦細JPG锛孭NG鍚庣紑鐨勬枃浠躲��");
+      } else {
+        const reader = new FileReader();
+        reader.readAsDataURL(file);
+        reader.onload = () => {
+          this.options.img = reader.result;
+          this.options.filename = file.name;
+        };
+      }
+    },
+    // 涓婁紶鍥剧墖
+    uploadImg() {
+      this.$refs.cropper.getCropBlob(data => {
+        let formData = new FormData();
+        formData.append("avatarfile", data, this.options.filename);
+        uploadAvatar(formData).then(response => {
+          this.open = false;
+          this.options.img = process.env.VUE_APP_BASE_API + response.imgUrl;
+          store.commit('SET_AVATAR', this.options.img);
+          this.$modal.msgSuccess("淇敼鎴愬姛");
+          this.visible = false;
+        });
+      });
+    },
+    // 瀹炴椂棰勮
+    realTime(data) {
+      this.previews = data;
+    },
+    // 鍏抽棴绐楀彛
+    closeDialog() {
+      this.options.img = store.getters.avatar
+      this.visible = false;
+      window.removeEventListener("resize", this.resizeHandler)
+    }
+  }
+};
+</script>
+<style scoped lang="scss">
+.user-info-head {
+  position: relative;
+  display: inline-block;
+  height: 120px;
+}
+
+.user-info-head:hover:after {
+  content: '+';
+  position: absolute;
+  left: 0;
+  right: 0;
+  top: 0;
+  bottom: 0;
+  color: #eee;
+  background: rgba(0, 0, 0, 0.5);
+  font-size: 24px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+  cursor: pointer;
+  line-height: 110px;
+  border-radius: 50%;
+}
+</style>
diff --git a/jcdm-ui/src/views/system/user/profile/userInfo.vue b/jcdm-ui/src/views/system/user/profile/userInfo.vue
new file mode 100644
index 0000000..c970dc9
--- /dev/null
+++ b/jcdm-ui/src/views/system/user/profile/userInfo.vue
@@ -0,0 +1,88 @@
+<template>
+  <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+    <el-form-item label="鐢ㄦ埛鏄电О" prop="nickName">
+      <el-input v-model="form.nickName" maxlength="30" />
+    </el-form-item> 
+    <el-form-item label="鎵嬫満鍙风爜" prop="phonenumber">
+      <el-input v-model="form.phonenumber" maxlength="11" />
+    </el-form-item>
+    <el-form-item label="閭" prop="email">
+      <el-input v-model="form.email" maxlength="50" />
+    </el-form-item>
+    <el-form-item label="鎬у埆">
+      <el-radio-group v-model="form.sex">
+        <el-radio label="0">鐢�</el-radio>
+        <el-radio label="1">濂�</el-radio>
+      </el-radio-group>
+    </el-form-item>
+    <el-form-item>
+      <el-button type="primary" size="mini" @click="submit">淇濆瓨</el-button>
+      <el-button type="danger" size="mini" @click="close">鍏抽棴</el-button>
+    </el-form-item>
+  </el-form>
+</template>
+
+<script>
+import { updateUserProfile } from "@/api/system/user";
+
+export default {
+  props: {
+    user: {
+      type: Object
+    }
+  },
+  data() {
+    return {
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        nickName: [
+          { required: true, message: "鐢ㄦ埛鏄电О涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        email: [
+          { required: true, message: "閭鍦板潃涓嶈兘涓虹┖", trigger: "blur" },
+          {
+            type: "email",
+            message: "璇疯緭鍏ユ纭殑閭鍦板潃",
+            trigger: ["blur", "change"]
+          }
+        ],
+        phonenumber: [
+          { required: true, message: "鎵嬫満鍙风爜涓嶈兘涓虹┖", trigger: "blur" },
+          {
+            pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
+            message: "璇疯緭鍏ユ纭殑鎵嬫満鍙风爜",
+            trigger: "blur"
+          }
+        ]
+      }
+    };
+  },
+  watch: {
+    user: {
+      handler(user) {
+        if (user) {
+          this.form = { nickName: user.nickName, phonenumber: user.phonenumber, email: user.email, sex: user.sex };
+        }
+      },
+      immediate: true
+    }
+  },
+  methods: {
+    submit() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          updateUserProfile(this.form).then(response => {
+            this.$modal.msgSuccess("淇敼鎴愬姛");
+            this.user.phonenumber = this.form.phonenumber;
+            this.user.email = this.form.email;
+          });
+        }
+      });
+    },
+    close() {
+      this.$tab.closePage();
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/tool/build/CodeTypeDialog.vue b/jcdm-ui/src/views/tool/build/CodeTypeDialog.vue
new file mode 100644
index 0000000..b5c2e2e
--- /dev/null
+++ b/jcdm-ui/src/views/tool/build/CodeTypeDialog.vue
@@ -0,0 +1,106 @@
+<template>
+  <div>
+    <el-dialog
+      v-bind="$attrs"
+      width="500px"
+      :close-on-click-modal="false"
+      :modal-append-to-body="false"
+      v-on="$listeners"
+      @open="onOpen"
+      @close="onClose"
+    >
+      <el-row :gutter="15">
+        <el-form
+          ref="elForm"
+          :model="formData"
+          :rules="rules"
+          size="medium"
+          label-width="100px"
+        >
+          <el-col :span="24">
+            <el-form-item label="鐢熸垚绫诲瀷" prop="type">
+              <el-radio-group v-model="formData.type">
+                <el-radio-button
+                  v-for="(item, index) in typeOptions"
+                  :key="index"
+                  :label="item.value"
+                  :disabled="item.disabled"
+                >
+                  {{ item.label }}
+                </el-radio-button>
+              </el-radio-group>
+            </el-form-item>
+            <el-form-item v-if="showFileName" label="鏂囦欢鍚�" prop="fileName">
+              <el-input v-model="formData.fileName" placeholder="璇疯緭鍏ユ枃浠跺悕" clearable />
+            </el-form-item>
+          </el-col>
+        </el-form>
+      </el-row>
+
+      <div slot="footer">
+        <el-button @click="close">
+          鍙栨秷
+        </el-button>
+        <el-button type="primary" @click="handleConfirm">
+          纭畾
+        </el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+<script>
+export default {
+  inheritAttrs: false,
+  props: ['showFileName'],
+  data() {
+    return {
+      formData: {
+        fileName: undefined,
+        type: 'file'
+      },
+      rules: {
+        fileName: [{
+          required: true,
+          message: '璇疯緭鍏ユ枃浠跺悕',
+          trigger: 'blur'
+        }],
+        type: [{
+          required: true,
+          message: '鐢熸垚绫诲瀷涓嶈兘涓虹┖',
+          trigger: 'change'
+        }]
+      },
+      typeOptions: [{
+        label: '椤甸潰',
+        value: 'file'
+      }, {
+        label: '寮圭獥',
+        value: 'dialog'
+      }]
+    }
+  },
+  computed: {
+  },
+  watch: {},
+  mounted() {},
+  methods: {
+    onOpen() {
+      if (this.showFileName) {
+        this.formData.fileName = `${+new Date()}.vue`
+      }
+    },
+    onClose() {
+    },
+    close(e) {
+      this.$emit('update:visible', false)
+    },
+    handleConfirm() {
+      this.$refs.elForm.validate(valid => {
+        if (!valid) return
+        this.$emit('confirm', { ...this.formData })
+        this.close()
+      })
+    }
+  }
+}
+</script>
diff --git a/jcdm-ui/src/views/tool/build/DraggableItem.vue b/jcdm-ui/src/views/tool/build/DraggableItem.vue
new file mode 100644
index 0000000..e881778
--- /dev/null
+++ b/jcdm-ui/src/views/tool/build/DraggableItem.vue
@@ -0,0 +1,100 @@
+<script>
+import draggable from 'vuedraggable'
+import render from '@/utils/generator/render'
+
+const components = {
+  itemBtns(h, element, index, parent) {
+    const { copyItem, deleteItem } = this.$listeners
+    return [
+      <span class="drawing-item-copy" title="澶嶅埗" onClick={event => {
+        copyItem(element, parent); event.stopPropagation()
+      }}>
+        <i class="el-icon-copy-document" />
+      </span>,
+      <span class="drawing-item-delete" title="鍒犻櫎" onClick={event => {
+        deleteItem(index, parent); event.stopPropagation()
+      }}>
+        <i class="el-icon-delete" />
+      </span>
+    ]
+  }
+}
+const layouts = {
+  colFormItem(h, element, index, parent) {
+    const { activeItem } = this.$listeners
+    let className = this.activeId === element.formId ? 'drawing-item active-from-item' : 'drawing-item'
+    if (this.formConf.unFocusedComponentBorder) className += ' unfocus-bordered'
+    return (
+      <el-col span={element.span} class={className}
+        nativeOnClick={event => { activeItem(element); event.stopPropagation() }}>
+        <el-form-item label-width={element.labelWidth ? `${element.labelWidth}px` : null}
+          label={element.label} required={element.required}>
+          <render key={element.renderKey} conf={element} onInput={ event => {
+            this.$set(element, 'defaultValue', event)
+          }} />
+        </el-form-item>
+        {components.itemBtns.apply(this, arguments)}
+      </el-col>
+    )
+  },
+  rowFormItem(h, element, index, parent) {
+    const { activeItem } = this.$listeners
+    const className = this.activeId === element.formId ? 'drawing-row-item active-from-item' : 'drawing-row-item'
+    let child = renderChildren.apply(this, arguments)
+    if (element.type === 'flex') {
+      child = <el-row type={element.type} justify={element.justify} align={element.align}>
+              {child}
+            </el-row>
+    }
+    return (
+      <el-col span={element.span}>
+        <el-row gutter={element.gutter} class={className}
+          nativeOnClick={event => { activeItem(element); event.stopPropagation() }}>
+          <span class="component-name">{element.componentName}</span>
+          <draggable list={element.children} animation={340} group="componentsGroup" class="drag-wrapper">
+            {child}
+          </draggable>
+          {components.itemBtns.apply(this, arguments)}
+        </el-row>
+      </el-col>
+    )
+  }
+}
+
+function renderChildren(h, element, index, parent) {
+  if (!Array.isArray(element.children)) return null
+  return element.children.map((el, i) => {
+    const layout = layouts[el.layout]
+    if (layout) {
+      return layout.call(this, h, el, i, element.children)
+    }
+    return layoutIsNotFound()
+  })
+}
+
+function layoutIsNotFound() {
+  throw new Error(`娌℃湁涓�${this.element.layout}鍖归厤鐨刲ayout`)
+}
+
+export default {
+  components: {
+    render,
+    draggable
+  },
+  props: [
+    'element',
+    'index',
+    'drawingList',
+    'activeId',
+    'formConf'
+  ],
+  render(h) {
+    const layout = layouts[this.element.layout]
+
+    if (layout) {
+      return layout.call(this, h, this.element, this.index, this.drawingList)
+    }
+    return layoutIsNotFound()
+  }
+}
+</script>
diff --git a/jcdm-ui/src/views/tool/build/IconsDialog.vue b/jcdm-ui/src/views/tool/build/IconsDialog.vue
new file mode 100644
index 0000000..958be50
--- /dev/null
+++ b/jcdm-ui/src/views/tool/build/IconsDialog.vue
@@ -0,0 +1,123 @@
+<template>
+  <div class="icon-dialog">
+    <el-dialog
+      v-bind="$attrs"
+      width="980px"
+      :modal-append-to-body="false"
+      v-on="$listeners"
+      @open="onOpen"
+      @close="onClose"
+    >
+      <div slot="title">
+        閫夋嫨鍥炬爣
+        <el-input
+          v-model="key"
+          size="mini"
+          :style="{width: '260px'}"
+          placeholder="璇疯緭鍏ュ浘鏍囧悕绉�"
+          prefix-icon="el-icon-search"
+          clearable
+        />
+      </div>
+      <ul class="icon-ul">
+        <li
+          v-for="icon in iconList"
+          :key="icon"
+          :class="active===icon?'active-item':''"
+          @click="onSelect(icon)"
+        >
+          <i :class="icon" />
+          <div>{{ icon }}</div>
+        </li>
+      </ul>
+    </el-dialog>
+  </div>
+</template>
+<script>
+import iconList from '@/utils/generator/icon.json'
+
+const originList = iconList.map(name => `el-icon-${name}`)
+
+export default {
+  inheritAttrs: false,
+  props: ['current'],
+  data() {
+    return {
+      iconList: originList,
+      active: null,
+      key: ''
+    }
+  },
+  watch: {
+    key(val) {
+      if (val) {
+        this.iconList = originList.filter(name => name.indexOf(val) > -1)
+      } else {
+        this.iconList = originList
+      }
+    }
+  },
+  methods: {
+    onOpen() {
+      this.active = this.current
+      this.key = ''
+    },
+    onClose() {},
+    onSelect(icon) {
+      this.active = icon
+      this.$emit('select', icon)
+      this.$emit('update:visible', false)
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+.icon-ul {
+  margin: 0;
+  padding: 0;
+  font-size: 0;
+  li {
+    list-style-type: none;
+    text-align: center;
+    font-size: 14px;
+    display: inline-block;
+    width: 16.66%;
+    box-sizing: border-box;
+    height: 108px;
+    padding: 15px 6px 6px 6px;
+    cursor: pointer;
+    overflow: hidden;
+    &:hover {
+      background: #f2f2f2;
+    }
+    &.active-item{
+      background: #e1f3fb;
+      color: #7a6df0
+    }
+    > i {
+      font-size: 30px;
+      line-height: 50px;
+    }
+  }
+}
+.icon-dialog {
+  ::v-deep .el-dialog {
+    border-radius: 8px;
+    margin-bottom: 0;
+    margin-top: 4vh !important;
+    display: flex;
+    flex-direction: column;
+    max-height: 92vh;
+    overflow: hidden;
+    box-sizing: border-box;
+    .el-dialog__header {
+      padding-top: 14px;
+    }
+    .el-dialog__body {
+      margin: 0 20px 20px 20px;
+      padding: 0;
+      overflow: auto;
+    }
+  }
+}
+</style>
diff --git a/jcdm-ui/src/views/tool/build/RightPanel.vue b/jcdm-ui/src/views/tool/build/RightPanel.vue
new file mode 100644
index 0000000..c2760eb
--- /dev/null
+++ b/jcdm-ui/src/views/tool/build/RightPanel.vue
@@ -0,0 +1,946 @@
+<template>
+  <div class="right-board">
+    <el-tabs v-model="currentTab" class="center-tabs">
+      <el-tab-pane label="缁勪欢灞炴��" name="field" />
+      <el-tab-pane label="琛ㄥ崟灞炴��" name="form" />
+    </el-tabs>
+    <div class="field-box">
+      <a class="document-link" target="_blank" :href="documentLink" title="鏌ョ湅缁勪欢鏂囨。">
+        <i class="el-icon-link" />
+      </a>
+      <el-scrollbar class="right-scrollbar">
+        <!-- 缁勪欢灞炴�� -->
+        <el-form v-show="currentTab==='field' && showField" size="small" label-width="90px">
+          <el-form-item v-if="activeData.changeTag" label="缁勪欢绫诲瀷">
+            <el-select
+              v-model="activeData.tagIcon"
+              placeholder="璇烽�夋嫨缁勪欢绫诲瀷"
+              :style="{width: '100%'}"
+              @change="tagChange"
+            >
+              <el-option-group v-for="group in tagList" :key="group.label" :label="group.label">
+                <el-option
+                  v-for="item in group.options"
+                  :key="item.label"
+                  :label="item.label"
+                  :value="item.tagIcon"
+                >
+                  <svg-icon class="node-icon" :icon-class="item.tagIcon" />
+                  <span> {{ item.label }}</span>
+                </el-option>
+              </el-option-group>
+            </el-select>
+          </el-form-item>
+          <el-form-item v-if="activeData.vModel!==undefined" label="瀛楁鍚�">
+            <el-input v-model="activeData.vModel" placeholder="璇疯緭鍏ュ瓧娈靛悕锛坴-model锛�" />
+          </el-form-item>
+          <el-form-item v-if="activeData.componentName!==undefined" label="缁勪欢鍚�">
+            {{ activeData.componentName }}
+          </el-form-item>
+          <el-form-item v-if="activeData.label!==undefined" label="鏍囬">
+            <el-input v-model="activeData.label" placeholder="璇疯緭鍏ユ爣棰�" />
+          </el-form-item>
+          <el-form-item v-if="activeData.placeholder!==undefined" label="鍗犱綅鎻愮ず">
+            <el-input v-model="activeData.placeholder" placeholder="璇疯緭鍏ュ崰浣嶆彁绀�" />
+          </el-form-item>
+          <el-form-item v-if="activeData['start-placeholder']!==undefined" label="寮�濮嬪崰浣�">
+            <el-input v-model="activeData['start-placeholder']" placeholder="璇疯緭鍏ュ崰浣嶆彁绀�" />
+          </el-form-item>
+          <el-form-item v-if="activeData['end-placeholder']!==undefined" label="缁撴潫鍗犱綅">
+            <el-input v-model="activeData['end-placeholder']" placeholder="璇疯緭鍏ュ崰浣嶆彁绀�" />
+          </el-form-item>
+          <el-form-item v-if="activeData.span!==undefined" label="琛ㄥ崟鏍呮牸">
+            <el-slider v-model="activeData.span" :max="24" :min="1" :marks="{12:''}" @change="spanChange" />
+          </el-form-item>
+          <el-form-item v-if="activeData.layout==='rowFormItem'" label="鏍呮牸闂撮殧">
+            <el-input-number v-model="activeData.gutter" :min="0" placeholder="鏍呮牸闂撮殧" />
+          </el-form-item>
+          <el-form-item v-if="activeData.layout==='rowFormItem'" label="甯冨眬妯″紡">
+            <el-radio-group v-model="activeData.type">
+              <el-radio-button label="default" />
+              <el-radio-button label="flex" />
+            </el-radio-group>
+          </el-form-item>
+          <el-form-item v-if="activeData.justify!==undefined&&activeData.type==='flex'" label="姘村钩鎺掑垪">
+            <el-select v-model="activeData.justify" placeholder="璇烽�夋嫨姘村钩鎺掑垪" :style="{width: '100%'}">
+              <el-option
+                v-for="(item, index) in justifyOptions"
+                :key="index"
+                :label="item.label"
+                :value="item.value"
+              />
+            </el-select>
+          </el-form-item>
+          <el-form-item v-if="activeData.align!==undefined&&activeData.type==='flex'" label="鍨傜洿鎺掑垪">
+            <el-radio-group v-model="activeData.align">
+              <el-radio-button label="top" />
+              <el-radio-button label="middle" />
+              <el-radio-button label="bottom" />
+            </el-radio-group>
+          </el-form-item>
+          <el-form-item v-if="activeData.labelWidth!==undefined" label="鏍囩瀹藉害">
+            <el-input v-model.number="activeData.labelWidth" type="number" placeholder="璇疯緭鍏ユ爣绛惧搴�" />
+          </el-form-item>
+          <el-form-item v-if="activeData.style&&activeData.style.width!==undefined" label="缁勪欢瀹藉害">
+            <el-input v-model="activeData.style.width" placeholder="璇疯緭鍏ョ粍浠跺搴�" clearable />
+          </el-form-item>
+          <el-form-item v-if="activeData.vModel!==undefined" label="榛樿鍊�">
+            <el-input
+              :value="setDefaultValue(activeData.defaultValue)"
+              placeholder="璇疯緭鍏ラ粯璁ゅ��"
+              @input="onDefaultValueInput"
+            />
+          </el-form-item>
+          <el-form-item v-if="activeData.tag==='el-checkbox-group'" label="鑷冲皯搴旈��">
+            <el-input-number
+              :value="activeData.min"
+              :min="0"
+              placeholder="鑷冲皯搴旈��"
+              @input="$set(activeData, 'min', $event?$event:undefined)"
+            />
+          </el-form-item>
+          <el-form-item v-if="activeData.tag==='el-checkbox-group'" label="鏈�澶氬彲閫�">
+            <el-input-number
+              :value="activeData.max"
+              :min="0"
+              placeholder="鏈�澶氬彲閫�"
+              @input="$set(activeData, 'max', $event?$event:undefined)"
+            />
+          </el-form-item>
+          <el-form-item v-if="activeData.prepend!==undefined" label="鍓嶇紑">
+            <el-input v-model="activeData.prepend" placeholder="璇疯緭鍏ュ墠缂�" />
+          </el-form-item>
+          <el-form-item v-if="activeData.append!==undefined" label="鍚庣紑">
+            <el-input v-model="activeData.append" placeholder="璇疯緭鍏ュ悗缂�" />
+          </el-form-item>
+          <el-form-item v-if="activeData['prefix-icon']!==undefined" label="鍓嶅浘鏍�">
+            <el-input v-model="activeData['prefix-icon']" placeholder="璇疯緭鍏ュ墠鍥炬爣鍚嶇О">
+              <el-button slot="append" icon="el-icon-thumb" @click="openIconsDialog('prefix-icon')">
+                閫夋嫨
+              </el-button>
+            </el-input>
+          </el-form-item>
+          <el-form-item v-if="activeData['suffix-icon'] !== undefined" label="鍚庡浘鏍�">
+            <el-input v-model="activeData['suffix-icon']" placeholder="璇疯緭鍏ュ悗鍥炬爣鍚嶇О">
+              <el-button slot="append" icon="el-icon-thumb" @click="openIconsDialog('suffix-icon')">
+                閫夋嫨
+              </el-button>
+            </el-input>
+          </el-form-item>
+          <el-form-item v-if="activeData.tag === 'el-cascader'" label="閫夐」鍒嗛殧绗�">
+            <el-input v-model="activeData.separator" placeholder="璇疯緭鍏ラ�夐」鍒嗛殧绗�" />
+          </el-form-item>
+          <el-form-item v-if="activeData.autosize !== undefined" label="鏈�灏忚鏁�">
+            <el-input-number v-model="activeData.autosize.minRows" :min="1" placeholder="鏈�灏忚鏁�" />
+          </el-form-item>
+          <el-form-item v-if="activeData.autosize !== undefined" label="鏈�澶ц鏁�">
+            <el-input-number v-model="activeData.autosize.maxRows" :min="1" placeholder="鏈�澶ц鏁�" />
+          </el-form-item>
+          <el-form-item v-if="activeData.min !== undefined" label="鏈�灏忓��">
+            <el-input-number v-model="activeData.min" placeholder="鏈�灏忓��" />
+          </el-form-item>
+          <el-form-item v-if="activeData.max !== undefined" label="鏈�澶у��">
+            <el-input-number v-model="activeData.max" placeholder="鏈�澶у��" />
+          </el-form-item>
+          <el-form-item v-if="activeData.step !== undefined" label="姝ラ暱">
+            <el-input-number v-model="activeData.step" placeholder="姝ユ暟" />
+          </el-form-item>
+          <el-form-item v-if="activeData.tag === 'el-input-number'" label="绮惧害">
+            <el-input-number v-model="activeData.precision" :min="0" placeholder="绮惧害" />
+          </el-form-item>
+          <el-form-item v-if="activeData.tag === 'el-input-number'" label="鎸夐挳浣嶇疆">
+            <el-radio-group v-model="activeData['controls-position']">
+              <el-radio-button label="">
+                榛樿
+              </el-radio-button>
+              <el-radio-button label="right">
+                鍙充晶
+              </el-radio-button>
+            </el-radio-group>
+          </el-form-item>
+          <el-form-item v-if="activeData.maxlength !== undefined" label="鏈�澶氳緭鍏�">
+            <el-input v-model="activeData.maxlength" placeholder="璇疯緭鍏ュ瓧绗﹂暱搴�">
+              <template slot="append">
+                涓瓧绗�
+              </template>
+            </el-input>
+          </el-form-item>
+          <el-form-item v-if="activeData['active-text'] !== undefined" label="寮�鍚彁绀�">
+            <el-input v-model="activeData['active-text']" placeholder="璇疯緭鍏ュ紑鍚彁绀�" />
+          </el-form-item>
+          <el-form-item v-if="activeData['inactive-text'] !== undefined" label="鍏抽棴鎻愮ず">
+            <el-input v-model="activeData['inactive-text']" placeholder="璇疯緭鍏ュ叧闂彁绀�" />
+          </el-form-item>
+          <el-form-item v-if="activeData['active-value'] !== undefined" label="寮�鍚��">
+            <el-input
+              :value="setDefaultValue(activeData['active-value'])"
+              placeholder="璇疯緭鍏ュ紑鍚��"
+              @input="onSwitchValueInput($event, 'active-value')"
+            />
+          </el-form-item>
+          <el-form-item v-if="activeData['inactive-value'] !== undefined" label="鍏抽棴鍊�">
+            <el-input
+              :value="setDefaultValue(activeData['inactive-value'])"
+              placeholder="璇疯緭鍏ュ叧闂��"
+              @input="onSwitchValueInput($event, 'inactive-value')"
+            />
+          </el-form-item>
+          <el-form-item
+            v-if="activeData.type !== undefined && 'el-date-picker' === activeData.tag"
+            label="鏃堕棿绫诲瀷"
+          >
+            <el-select
+              v-model="activeData.type"
+              placeholder="璇烽�夋嫨鏃堕棿绫诲瀷"
+              :style="{ width: '100%' }"
+              @change="dateTypeChange"
+            >
+              <el-option
+                v-for="(item, index) in dateOptions"
+                :key="index"
+                :label="item.label"
+                :value="item.value"
+              />
+            </el-select>
+          </el-form-item>
+          <el-form-item v-if="activeData.name !== undefined" label="鏂囦欢瀛楁鍚�">
+            <el-input v-model="activeData.name" placeholder="璇疯緭鍏ヤ笂浼犳枃浠跺瓧娈靛悕" />
+          </el-form-item>
+          <el-form-item v-if="activeData.accept !== undefined" label="鏂囦欢绫诲瀷">
+            <el-select
+              v-model="activeData.accept"
+              placeholder="璇烽�夋嫨鏂囦欢绫诲瀷"
+              :style="{ width: '100%' }"
+              clearable
+            >
+              <el-option label="鍥剧墖" value="image/*" />
+              <el-option label="瑙嗛" value="video/*" />
+              <el-option label="闊抽" value="audio/*" />
+              <el-option label="excel" value=".xls,.xlsx" />
+              <el-option label="word" value=".doc,.docx" />
+              <el-option label="pdf" value=".pdf" />
+              <el-option label="txt" value=".txt" />
+            </el-select>
+          </el-form-item>
+          <el-form-item v-if="activeData.fileSize !== undefined" label="鏂囦欢澶у皬">
+            <el-input v-model.number="activeData.fileSize" placeholder="璇疯緭鍏ユ枃浠跺ぇ灏�">
+              <el-select slot="append" v-model="activeData.sizeUnit" :style="{ width: '66px' }">
+                <el-option label="KB" value="KB" />
+                <el-option label="MB" value="MB" />
+                <el-option label="GB" value="GB" />
+              </el-select>
+            </el-input>
+          </el-form-item>
+          <el-form-item v-if="activeData.action !== undefined" label="涓婁紶鍦板潃">
+            <el-input v-model="activeData.action" placeholder="璇疯緭鍏ヤ笂浼犲湴鍧�" clearable />
+          </el-form-item>
+          <el-form-item v-if="activeData['list-type'] !== undefined" label="鍒楄〃绫诲瀷">
+            <el-radio-group v-model="activeData['list-type']" size="small">
+              <el-radio-button label="text">
+                text
+              </el-radio-button>
+              <el-radio-button label="picture">
+                picture
+              </el-radio-button>
+              <el-radio-button label="picture-card">
+                picture-card
+              </el-radio-button>
+            </el-radio-group>
+          </el-form-item>
+          <el-form-item
+            v-if="activeData.buttonText !== undefined"
+            v-show="'picture-card' !== activeData['list-type']"
+            label="鎸夐挳鏂囧瓧"
+          >
+            <el-input v-model="activeData.buttonText" placeholder="璇疯緭鍏ユ寜閽枃瀛�" />
+          </el-form-item>
+          <el-form-item v-if="activeData['range-separator'] !== undefined" label="鍒嗛殧绗�">
+            <el-input v-model="activeData['range-separator']" placeholder="璇疯緭鍏ュ垎闅旂" />
+          </el-form-item>
+          <el-form-item v-if="activeData['picker-options'] !== undefined" label="鏃堕棿娈�">
+            <el-input
+              v-model="activeData['picker-options'].selectableRange"
+              placeholder="璇疯緭鍏ユ椂闂存"
+            />
+          </el-form-item>
+          <el-form-item v-if="activeData.format !== undefined" label="鏃堕棿鏍煎紡">
+            <el-input
+              :value="activeData.format"
+              placeholder="璇疯緭鍏ユ椂闂存牸寮�"
+              @input="setTimeValue($event)"
+            />
+          </el-form-item>
+          <template v-if="['el-checkbox-group', 'el-radio-group', 'el-select'].indexOf(activeData.tag) > -1">
+            <el-divider>閫夐」</el-divider>
+            <draggable
+              :list="activeData.options"
+              :animation="340"
+              group="selectItem"
+              handle=".option-drag"
+            >
+              <div v-for="(item, index) in activeData.options" :key="index" class="select-item">
+                <div class="select-line-icon option-drag">
+                  <i class="el-icon-s-operation" />
+                </div>
+                <el-input v-model="item.label" placeholder="閫夐」鍚�" size="small" />
+                <el-input
+                  placeholder="閫夐」鍊�"
+                  size="small"
+                  :value="item.value"
+                  @input="setOptionValue(item, $event)"
+                />
+                <div class="close-btn select-line-icon" @click="activeData.options.splice(index, 1)">
+                  <i class="el-icon-remove-outline" />
+                </div>
+              </div>
+            </draggable>
+            <div style="margin-left: 20px;">
+              <el-button
+                style="padding-bottom: 0"
+                icon="el-icon-circle-plus-outline"
+                type="text"
+                @click="addSelectItem"
+              >
+                娣诲姞閫夐」
+              </el-button>
+            </div>
+            <el-divider />
+          </template>
+
+          <template v-if="['el-cascader'].indexOf(activeData.tag) > -1">
+            <el-divider>閫夐」</el-divider>
+            <el-form-item label="鏁版嵁绫诲瀷">
+              <el-radio-group v-model="activeData.dataType" size="small">
+                <el-radio-button label="dynamic">
+                  鍔ㄦ�佹暟鎹�
+                </el-radio-button>
+                <el-radio-button label="static">
+                  闈欐�佹暟鎹�
+                </el-radio-button>
+              </el-radio-group>
+            </el-form-item>
+
+            <template v-if="activeData.dataType === 'dynamic'">
+              <el-form-item label="鏍囩閿悕">
+                <el-input v-model="activeData.labelKey" placeholder="璇疯緭鍏ユ爣绛鹃敭鍚�" />
+              </el-form-item>
+              <el-form-item label="鍊奸敭鍚�">
+                <el-input v-model="activeData.valueKey" placeholder="璇疯緭鍏ュ�奸敭鍚�" />
+              </el-form-item>
+              <el-form-item label="瀛愮骇閿悕">
+                <el-input v-model="activeData.childrenKey" placeholder="璇疯緭鍏ュ瓙绾ч敭鍚�" />
+              </el-form-item>
+            </template>
+
+            <el-tree
+              v-if="activeData.dataType === 'static'"
+              draggable
+              :data="activeData.options"
+              node-key="id"
+              :expand-on-click-node="false"
+              :render-content="renderContent"
+            />
+            <div v-if="activeData.dataType === 'static'" style="margin-left: 20px">
+              <el-button
+                style="padding-bottom: 0"
+                icon="el-icon-circle-plus-outline"
+                type="text"
+                @click="addTreeItem"
+              >
+                娣诲姞鐖剁骇
+              </el-button>
+            </div>
+            <el-divider />
+          </template>
+
+          <el-form-item v-if="activeData.optionType !== undefined" label="閫夐」鏍峰紡">
+            <el-radio-group v-model="activeData.optionType">
+              <el-radio-button label="default">
+                榛樿
+              </el-radio-button>
+              <el-radio-button label="button">
+                鎸夐挳
+              </el-radio-button>
+            </el-radio-group>
+          </el-form-item>
+          <el-form-item v-if="activeData['active-color'] !== undefined" label="寮�鍚鑹�">
+            <el-color-picker v-model="activeData['active-color']" />
+          </el-form-item>
+          <el-form-item v-if="activeData['inactive-color'] !== undefined" label="鍏抽棴棰滆壊">
+            <el-color-picker v-model="activeData['inactive-color']" />
+          </el-form-item>
+
+          <el-form-item v-if="activeData['allow-half'] !== undefined" label="鍏佽鍗婇��">
+            <el-switch v-model="activeData['allow-half']" />
+          </el-form-item>
+          <el-form-item v-if="activeData['show-text'] !== undefined" label="杈呭姪鏂囧瓧">
+            <el-switch v-model="activeData['show-text']" @change="rateTextChange" />
+          </el-form-item>
+          <el-form-item v-if="activeData['show-score'] !== undefined" label="鏄剧ず鍒嗘暟">
+            <el-switch v-model="activeData['show-score']" @change="rateScoreChange" />
+          </el-form-item>
+          <el-form-item v-if="activeData['show-stops'] !== undefined" label="鏄剧ず闂存柇鐐�">
+            <el-switch v-model="activeData['show-stops']" />
+          </el-form-item>
+          <el-form-item v-if="activeData.range !== undefined" label="鑼冨洿閫夋嫨">
+            <el-switch v-model="activeData.range" @change="rangeChange" />
+          </el-form-item>
+          <el-form-item
+            v-if="activeData.border !== undefined && activeData.optionType === 'default'"
+            label="鏄惁甯﹁竟妗�"
+          >
+            <el-switch v-model="activeData.border" />
+          </el-form-item>
+          <el-form-item v-if="activeData.tag === 'el-color-picker'" label="棰滆壊鏍煎紡">
+            <el-select
+              v-model="activeData['color-format']"
+              placeholder="璇烽�夋嫨棰滆壊鏍煎紡"
+              :style="{ width: '100%' }"
+              @change="colorFormatChange"
+            >
+              <el-option
+                v-for="(item, index) in colorFormatOptions"
+                :key="index"
+                :label="item.label"
+                :value="item.value"
+              />
+            </el-select>
+          </el-form-item>
+          <el-form-item
+            v-if="activeData.size !== undefined &&
+              (activeData.optionType === 'button' ||
+                activeData.border ||
+                activeData.tag === 'el-color-picker')"
+            label="閫夐」灏哄"
+          >
+            <el-radio-group v-model="activeData.size">
+              <el-radio-button label="medium">
+                涓瓑
+              </el-radio-button>
+              <el-radio-button label="small">
+                杈冨皬
+              </el-radio-button>
+              <el-radio-button label="mini">
+                杩蜂綘
+              </el-radio-button>
+            </el-radio-group>
+          </el-form-item>
+          <el-form-item v-if="activeData['show-word-limit'] !== undefined" label="杈撳叆缁熻">
+            <el-switch v-model="activeData['show-word-limit']" />
+          </el-form-item>
+          <el-form-item v-if="activeData.tag === 'el-input-number'" label="涓ユ牸姝ユ暟">
+            <el-switch v-model="activeData['step-strictly']" />
+          </el-form-item>
+          <el-form-item v-if="activeData.tag === 'el-cascader'" label="鏄惁澶氶��">
+            <el-switch v-model="activeData.props.props.multiple" />
+          </el-form-item>
+          <el-form-item v-if="activeData.tag === 'el-cascader'" label="灞曠ず鍏ㄨ矾寰�">
+            <el-switch v-model="activeData['show-all-levels']" />
+          </el-form-item>
+          <el-form-item v-if="activeData.tag === 'el-cascader'" label="鍙惁绛涢��">
+            <el-switch v-model="activeData.filterable" />
+          </el-form-item>
+          <el-form-item v-if="activeData.clearable !== undefined" label="鑳藉惁娓呯┖">
+            <el-switch v-model="activeData.clearable" />
+          </el-form-item>
+          <el-form-item v-if="activeData.showTip !== undefined" label="鏄剧ず鎻愮ず">
+            <el-switch v-model="activeData.showTip" />
+          </el-form-item>
+          <el-form-item v-if="activeData.multiple !== undefined" label="澶氶�夋枃浠�">
+            <el-switch v-model="activeData.multiple" />
+          </el-form-item>
+          <el-form-item v-if="activeData['auto-upload'] !== undefined" label="鑷姩涓婁紶">
+            <el-switch v-model="activeData['auto-upload']" />
+          </el-form-item>
+          <el-form-item v-if="activeData.readonly !== undefined" label="鏄惁鍙">
+            <el-switch v-model="activeData.readonly" />
+          </el-form-item>
+          <el-form-item v-if="activeData.disabled !== undefined" label="鏄惁绂佺敤">
+            <el-switch v-model="activeData.disabled" />
+          </el-form-item>
+          <el-form-item v-if="activeData.tag === 'el-select'" label="鏄惁鍙悳绱�">
+            <el-switch v-model="activeData.filterable" />
+          </el-form-item>
+          <el-form-item v-if="activeData.tag === 'el-select'" label="鏄惁澶氶��">
+            <el-switch v-model="activeData.multiple" @change="multipleChange" />
+          </el-form-item>
+          <el-form-item v-if="activeData.required !== undefined" label="鏄惁蹇呭~">
+            <el-switch v-model="activeData.required" />
+          </el-form-item>
+
+          <template v-if="activeData.layoutTree">
+            <el-divider>甯冨眬缁撴瀯鏍�</el-divider>
+            <el-tree
+              :data="[activeData]"
+              :props="layoutTreeProps"
+              node-key="renderKey"
+              default-expand-all
+              draggable
+            >
+              <span slot-scope="{ node, data }">
+                <span class="node-label">
+                  <svg-icon class="node-icon" :icon-class="data.tagIcon" />
+                  {{ node.label }}
+                </span>
+              </span>
+            </el-tree>
+          </template>
+
+          <template v-if="activeData.layout === 'colFormItem' && activeData.tag !== 'el-button'">
+            <el-divider>姝e垯鏍¢獙</el-divider>
+            <div
+              v-for="(item, index) in activeData.regList"
+              :key="index"
+              class="reg-item"
+            >
+              <span class="close-btn" @click="activeData.regList.splice(index, 1)">
+                <i class="el-icon-close" />
+              </span>
+              <el-form-item label="琛ㄨ揪寮�">
+                <el-input v-model="item.pattern" placeholder="璇疯緭鍏ユ鍒�" />
+              </el-form-item>
+              <el-form-item label="閿欒鎻愮ず" style="margin-bottom:0">
+                <el-input v-model="item.message" placeholder="璇疯緭鍏ラ敊璇彁绀�" />
+              </el-form-item>
+            </div>
+            <div style="margin-left: 20px">
+              <el-button icon="el-icon-circle-plus-outline" type="text" @click="addReg">
+                娣诲姞瑙勫垯
+              </el-button>
+            </div>
+          </template>
+        </el-form>
+        <!-- 琛ㄥ崟灞炴�� -->
+        <el-form v-show="currentTab === 'form'" size="small" label-width="90px">
+          <el-form-item label="琛ㄥ崟鍚�">
+            <el-input v-model="formConf.formRef" placeholder="璇疯緭鍏ヨ〃鍗曞悕锛坮ef锛�" />
+          </el-form-item>
+          <el-form-item label="琛ㄥ崟妯″瀷">
+            <el-input v-model="formConf.formModel" placeholder="璇疯緭鍏ユ暟鎹ā鍨�" />
+          </el-form-item>
+          <el-form-item label="鏍¢獙妯″瀷">
+            <el-input v-model="formConf.formRules" placeholder="璇疯緭鍏ユ牎楠屾ā鍨�" />
+          </el-form-item>
+          <el-form-item label="琛ㄥ崟灏哄">
+            <el-radio-group v-model="formConf.size">
+              <el-radio-button label="medium">
+                涓瓑
+              </el-radio-button>
+              <el-radio-button label="small">
+                杈冨皬
+              </el-radio-button>
+              <el-radio-button label="mini">
+                杩蜂綘
+              </el-radio-button>
+            </el-radio-group>
+          </el-form-item>
+          <el-form-item label="鏍囩瀵归綈">
+            <el-radio-group v-model="formConf.labelPosition">
+              <el-radio-button label="left">
+                宸﹀榻�
+              </el-radio-button>
+              <el-radio-button label="right">
+                鍙冲榻�
+              </el-radio-button>
+              <el-radio-button label="top">
+                椤堕儴瀵归綈
+              </el-radio-button>
+            </el-radio-group>
+          </el-form-item>
+          <el-form-item label="鏍囩瀹藉害">
+            <el-input-number v-model="formConf.labelWidth" placeholder="鏍囩瀹藉害" />
+          </el-form-item>
+          <el-form-item label="鏍呮牸闂撮殧">
+            <el-input-number v-model="formConf.gutter" :min="0" placeholder="鏍呮牸闂撮殧" />
+          </el-form-item>
+          <el-form-item label="绂佺敤琛ㄥ崟">
+            <el-switch v-model="formConf.disabled" />
+          </el-form-item>
+          <el-form-item label="琛ㄥ崟鎸夐挳">
+            <el-switch v-model="formConf.formBtns" />
+          </el-form-item>
+          <el-form-item label="鏄剧ず鏈�変腑缁勪欢杈规">
+            <el-switch v-model="formConf.unFocusedComponentBorder" />
+          </el-form-item>
+        </el-form>
+      </el-scrollbar>
+    </div>
+
+    <treeNode-dialog :visible.sync="dialogVisible" title="娣诲姞閫夐」" @commit="addNode" />
+    <icons-dialog :visible.sync="iconsVisible" :current="activeData[currentIconModel]" @select="setIcon" />
+  </div>
+</template>
+
+<script>
+import { isArray } from 'util'
+import draggable from 'vuedraggable'
+import TreeNodeDialog from './TreeNodeDialog'
+import { isNumberStr } from '@/utils/index'
+import IconsDialog from './IconsDialog'
+import {
+  inputComponents,
+  selectComponents,
+  layoutComponents
+} from '@/utils/generator/config'
+
+const dateTimeFormat = {
+  date: 'yyyy-MM-dd',
+  week: 'yyyy 绗� WW 鍛�',
+  month: 'yyyy-MM',
+  year: 'yyyy',
+  datetime: 'yyyy-MM-dd HH:mm:ss',
+  daterange: 'yyyy-MM-dd',
+  monthrange: 'yyyy-MM',
+  datetimerange: 'yyyy-MM-dd HH:mm:ss'
+}
+
+export default {
+  components: {
+    draggable,
+    TreeNodeDialog,
+    IconsDialog
+  },
+  props: ['showField', 'activeData', 'formConf'],
+  data() {
+    return {
+      currentTab: 'field',
+      currentNode: null,
+      dialogVisible: false,
+      iconsVisible: false,
+      currentIconModel: null,
+      dateTypeOptions: [
+        {
+          label: '鏃�(date)',
+          value: 'date'
+        },
+        {
+          label: '鍛�(week)',
+          value: 'week'
+        },
+        {
+          label: '鏈�(month)',
+          value: 'month'
+        },
+        {
+          label: '骞�(year)',
+          value: 'year'
+        },
+        {
+          label: '鏃ユ湡鏃堕棿(datetime)',
+          value: 'datetime'
+        }
+      ],
+      dateRangeTypeOptions: [
+        {
+          label: '鏃ユ湡鑼冨洿(daterange)',
+          value: 'daterange'
+        },
+        {
+          label: '鏈堣寖鍥�(monthrange)',
+          value: 'monthrange'
+        },
+        {
+          label: '鏃ユ湡鏃堕棿鑼冨洿(datetimerange)',
+          value: 'datetimerange'
+        }
+      ],
+      colorFormatOptions: [
+        {
+          label: 'hex',
+          value: 'hex'
+        },
+        {
+          label: 'rgb',
+          value: 'rgb'
+        },
+        {
+          label: 'rgba',
+          value: 'rgba'
+        },
+        {
+          label: 'hsv',
+          value: 'hsv'
+        },
+        {
+          label: 'hsl',
+          value: 'hsl'
+        }
+      ],
+      justifyOptions: [
+        {
+          label: 'start',
+          value: 'start'
+        },
+        {
+          label: 'end',
+          value: 'end'
+        },
+        {
+          label: 'center',
+          value: 'center'
+        },
+        {
+          label: 'space-around',
+          value: 'space-around'
+        },
+        {
+          label: 'space-between',
+          value: 'space-between'
+        }
+      ],
+      layoutTreeProps: {
+        label(data, node) {
+          return data.componentName || `${data.label}: ${data.vModel}`
+        }
+      }
+    }
+  },
+  computed: {
+    documentLink() {
+      return (
+        this.activeData.document
+        || 'https://element.eleme.cn/#/zh-CN/component/installation'
+      )
+    },
+    dateOptions() {
+      if (
+        this.activeData.type !== undefined
+        && this.activeData.tag === 'el-date-picker'
+      ) {
+        if (this.activeData['start-placeholder'] === undefined) {
+          return this.dateTypeOptions
+        }
+        return this.dateRangeTypeOptions
+      }
+      return []
+    },
+    tagList() {
+      return [
+        {
+          label: '杈撳叆鍨嬬粍浠�',
+          options: inputComponents
+        },
+        {
+          label: '閫夋嫨鍨嬬粍浠�',
+          options: selectComponents
+        }
+      ]
+    }
+  },
+  methods: {
+    addReg() {
+      this.activeData.regList.push({
+        pattern: '',
+        message: ''
+      })
+    },
+    addSelectItem() {
+      this.activeData.options.push({
+        label: '',
+        value: ''
+      })
+    },
+    addTreeItem() {
+      ++this.idGlobal
+      this.dialogVisible = true
+      this.currentNode = this.activeData.options
+    },
+    renderContent(h, { node, data, store }) {
+      return (
+        <div class="custom-tree-node">
+          <span>{node.label}</span>
+          <span class="node-operation">
+            <i on-click={() => this.append(data)}
+              class="el-icon-plus"
+              title="娣诲姞"
+            ></i>
+            <i on-click={() => this.remove(node, data)}
+              class="el-icon-delete"
+              title="鍒犻櫎"
+            ></i>
+          </span>
+        </div>
+      )
+    },
+    append(data) {
+      if (!data.children) {
+        this.$set(data, 'children', [])
+      }
+      this.dialogVisible = true
+      this.currentNode = data.children
+    },
+    remove(node, data) {
+      const { parent } = node
+      const children = parent.data.children || parent.data
+      const index = children.findIndex(d => d.id === data.id)
+      children.splice(index, 1)
+    },
+    addNode(data) {
+      this.currentNode.push(data)
+    },
+    setOptionValue(item, val) {
+      item.value = isNumberStr(val) ? +val : val
+    },
+    setDefaultValue(val) {
+      if (Array.isArray(val)) {
+        return val.join(',')
+      }
+      if (['string', 'number'].indexOf(val) > -1) {
+        return val
+      }
+      if (typeof val === 'boolean') {
+        return `${val}`
+      }
+      return val
+    },
+    onDefaultValueInput(str) {
+      if (isArray(this.activeData.defaultValue)) {
+        // 鏁扮粍
+        this.$set(
+          this.activeData,
+          'defaultValue',
+          str.split(',').map(val => (isNumberStr(val) ? +val : val))
+        )
+      } else if (['true', 'false'].indexOf(str) > -1) {
+        // 甯冨皵
+        this.$set(this.activeData, 'defaultValue', JSON.parse(str))
+      } else {
+        // 瀛楃涓插拰鏁板瓧
+        this.$set(
+          this.activeData,
+          'defaultValue',
+          isNumberStr(str) ? +str : str
+        )
+      }
+    },
+    onSwitchValueInput(val, name) {
+      if (['true', 'false'].indexOf(val) > -1) {
+        this.$set(this.activeData, name, JSON.parse(val))
+      } else {
+        this.$set(this.activeData, name, isNumberStr(val) ? +val : val)
+      }
+    },
+    setTimeValue(val, type) {
+      const valueFormat = type === 'week' ? dateTimeFormat.date : val
+      this.$set(this.activeData, 'defaultValue', null)
+      this.$set(this.activeData, 'value-format', valueFormat)
+      this.$set(this.activeData, 'format', val)
+    },
+    spanChange(val) {
+      this.formConf.span = val
+    },
+    multipleChange(val) {
+      this.$set(this.activeData, 'defaultValue', val ? [] : '')
+    },
+    dateTypeChange(val) {
+      this.setTimeValue(dateTimeFormat[val], val)
+    },
+    rangeChange(val) {
+      this.$set(
+        this.activeData,
+        'defaultValue',
+        val ? [this.activeData.min, this.activeData.max] : this.activeData.min
+      )
+    },
+    rateTextChange(val) {
+      if (val) this.activeData['show-score'] = false
+    },
+    rateScoreChange(val) {
+      if (val) this.activeData['show-text'] = false
+    },
+    colorFormatChange(val) {
+      this.activeData.defaultValue = null
+      this.activeData['show-alpha'] = val.indexOf('a') > -1
+      this.activeData.renderKey = +new Date() // 鏇存柊renderKey,閲嶆柊娓叉煋璇ョ粍浠�
+    },
+    openIconsDialog(model) {
+      this.iconsVisible = true
+      this.currentIconModel = model
+    },
+    setIcon(val) {
+      this.activeData[this.currentIconModel] = val
+    },
+    tagChange(tagIcon) {
+      let target = inputComponents.find(item => item.tagIcon === tagIcon)
+      if (!target) target = selectComponents.find(item => item.tagIcon === tagIcon)
+      this.$emit('tag-change', target)
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.right-board {
+  width: 350px;
+  position: absolute;
+  right: 0;
+  top: 0;
+  padding-top: 3px;
+  .field-box {
+    position: relative;
+    height: calc(100vh - 42px);
+    box-sizing: border-box;
+    overflow: hidden;
+  }
+  .el-scrollbar {
+    height: 100%;
+  }
+}
+.select-item {
+  display: flex;
+  border: 1px dashed #fff;
+  box-sizing: border-box;
+  & .close-btn {
+    cursor: pointer;
+    color: #f56c6c;
+  }
+  & .el-input + .el-input {
+    margin-left: 4px;
+  }
+}
+.select-item + .select-item {
+  margin-top: 4px;
+}
+.select-item.sortable-chosen {
+  border: 1px dashed #409eff;
+}
+.select-line-icon {
+  line-height: 32px;
+  font-size: 22px;
+  padding: 0 4px;
+  color: #777;
+}
+.option-drag {
+  cursor: move;
+}
+.time-range {
+  .el-date-editor {
+    width: 227px;
+  }
+  ::v-deep .el-icon-time {
+    display: none;
+  }
+}
+.document-link {
+  position: absolute;
+  display: block;
+  width: 26px;
+  height: 26px;
+  top: 0;
+  left: 0;
+  cursor: pointer;
+  background: #409eff;
+  z-index: 1;
+  border-radius: 0 0 6px 0;
+  text-align: center;
+  line-height: 26px;
+  color: #fff;
+  font-size: 18px;
+}
+.node-label{
+  font-size: 14px;
+}
+.node-icon{
+  color: #bebfc3;
+}
+</style>
diff --git a/jcdm-ui/src/views/tool/build/TreeNodeDialog.vue b/jcdm-ui/src/views/tool/build/TreeNodeDialog.vue
new file mode 100644
index 0000000..fa7f0b2
--- /dev/null
+++ b/jcdm-ui/src/views/tool/build/TreeNodeDialog.vue
@@ -0,0 +1,149 @@
+<template>
+  <div>
+    <el-dialog
+      v-bind="$attrs"
+      :close-on-click-modal="false"
+      :modal-append-to-body="false"
+      v-on="$listeners"
+      @open="onOpen"
+      @close="onClose"
+    >
+      <el-row :gutter="0">
+        <el-form
+          ref="elForm"
+          :model="formData"
+          :rules="rules"
+          size="small"
+          label-width="100px"
+        >
+          <el-col :span="24">
+            <el-form-item
+              label="閫夐」鍚�"
+              prop="label"
+            >
+              <el-input
+                v-model="formData.label"
+                placeholder="璇疯緭鍏ラ�夐」鍚�"
+                clearable
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="24">
+            <el-form-item
+              label="閫夐」鍊�"
+              prop="value"
+            >
+              <el-input
+                v-model="formData.value"
+                placeholder="璇疯緭鍏ラ�夐」鍊�"
+                clearable
+              >
+                <el-select
+                  slot="append"
+                  v-model="dataType"
+                  :style="{width: '100px'}"
+                >
+                  <el-option
+                    v-for="(item, index) in dataTypeOptions"
+                    :key="index"
+                    :label="item.label"
+                    :value="item.value"
+                    :disabled="item.disabled"
+                  />
+                </el-select>
+              </el-input>
+            </el-form-item>
+          </el-col>
+        </el-form>
+      </el-row>
+      <div slot="footer">
+        <el-button
+          type="primary"
+          @click="handleConfirm"
+        >
+          纭畾
+        </el-button>
+        <el-button @click="close">
+          鍙栨秷
+        </el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+<script>
+import { isNumberStr } from '@/utils/index'
+
+export default {
+  components: {},
+  inheritAttrs: false,
+  props: [],
+  data() {
+    return {
+      id: 100,
+      formData: {
+        label: undefined,
+        value: undefined
+      },
+      rules: {
+        label: [
+          {
+            required: true,
+            message: '璇疯緭鍏ラ�夐」鍚�',
+            trigger: 'blur'
+          }
+        ],
+        value: [
+          {
+            required: true,
+            message: '璇疯緭鍏ラ�夐」鍊�',
+            trigger: 'blur'
+          }
+        ]
+      },
+      dataType: 'string',
+      dataTypeOptions: [
+        {
+          label: '瀛楃涓�',
+          value: 'string'
+        },
+        {
+          label: '鏁板瓧',
+          value: 'number'
+        }
+      ]
+    }
+  },
+  computed: {},
+  watch: {
+    // eslint-disable-next-line func-names
+    'formData.value': function (val) {
+      this.dataType = isNumberStr(val) ? 'number' : 'string'
+    }
+  },
+  created() {},
+  mounted() {},
+  methods: {
+    onOpen() {
+      this.formData = {
+        label: undefined,
+        value: undefined
+      }
+    },
+    onClose() {},
+    close() {
+      this.$emit('update:visible', false)
+    },
+    handleConfirm() {
+      this.$refs.elForm.validate(valid => {
+        if (!valid) return
+        if (this.dataType === 'number') {
+          this.formData.value = parseFloat(this.formData.value)
+        }
+        this.formData.id = this.id++
+        this.$emit('commit', this.formData)
+        this.close()
+      })
+    }
+  }
+}
+</script>
diff --git a/jcdm-ui/src/views/tool/build/index.vue b/jcdm-ui/src/views/tool/build/index.vue
new file mode 100644
index 0000000..2bd298b
--- /dev/null
+++ b/jcdm-ui/src/views/tool/build/index.vue
@@ -0,0 +1,768 @@
+<template>
+  <div class="container">
+    <div class="left-board">
+      <div class="logo-wrapper">
+        <div class="logo">
+          <img :src="logo" alt="logo"> Form Generator
+        </div>
+      </div>
+      <el-scrollbar class="left-scrollbar">
+        <div class="components-list">
+          <div class="components-title">
+            <svg-icon icon-class="component" />杈撳叆鍨嬬粍浠�
+          </div>
+          <draggable
+            class="components-draggable"
+            :list="inputComponents"
+            :group="{ name: 'componentsGroup', pull: 'clone', put: false }"
+            :clone="cloneComponent"
+            draggable=".components-item"
+            :sort="false"
+            @end="onEnd"
+          >
+            <div
+              v-for="(element, index) in inputComponents" :key="index" class="components-item"
+              @click="addComponent(element)"
+            >
+              <div class="components-body">
+                <svg-icon :icon-class="element.tagIcon" />
+                {{ element.label }}
+              </div>
+            </div>
+          </draggable>
+          <div class="components-title">
+            <svg-icon icon-class="component" />閫夋嫨鍨嬬粍浠�
+          </div>
+          <draggable
+            class="components-draggable"
+            :list="selectComponents"
+            :group="{ name: 'componentsGroup', pull: 'clone', put: false }"
+            :clone="cloneComponent"
+            draggable=".components-item"
+            :sort="false"
+            @end="onEnd"
+          >
+            <div
+              v-for="(element, index) in selectComponents"
+              :key="index"
+              class="components-item"
+              @click="addComponent(element)"
+            >
+              <div class="components-body">
+                <svg-icon :icon-class="element.tagIcon" />
+                {{ element.label }}
+              </div>
+            </div>
+          </draggable>
+          <div class="components-title">
+            <svg-icon icon-class="component" /> 甯冨眬鍨嬬粍浠�
+          </div>
+          <draggable
+            class="components-draggable" :list="layoutComponents"
+            :group="{ name: 'componentsGroup', pull: 'clone', put: false }" :clone="cloneComponent"
+            draggable=".components-item" :sort="false" @end="onEnd"
+          >
+            <div
+              v-for="(element, index) in layoutComponents" :key="index" class="components-item"
+              @click="addComponent(element)"
+            >
+              <div class="components-body">
+                <svg-icon :icon-class="element.tagIcon" />
+                {{ element.label }}
+              </div>
+            </div>
+          </draggable>
+        </div>
+      </el-scrollbar>
+    </div>
+
+    <div class="center-board">
+      <div class="action-bar">
+        <el-button icon="el-icon-download" type="text" @click="download">
+          瀵煎嚭vue鏂囦欢
+        </el-button>
+        <el-button class="copy-btn-main" icon="el-icon-document-copy" type="text" @click="copy">
+          澶嶅埗浠g爜
+        </el-button>
+        <el-button class="delete-btn" icon="el-icon-delete" type="text" @click="empty">
+          娓呯┖
+        </el-button>
+      </div>
+      <el-scrollbar class="center-scrollbar">
+        <el-row class="center-board-row" :gutter="formConf.gutter">
+          <el-form
+            :size="formConf.size"
+            :label-position="formConf.labelPosition"
+            :disabled="formConf.disabled"
+            :label-width="formConf.labelWidth + 'px'"
+          >
+            <draggable class="drawing-board" :list="drawingList" :animation="340" group="componentsGroup">
+              <draggable-item
+                v-for="(element, index) in drawingList"
+                :key="element.renderKey"
+                :drawing-list="drawingList"
+                :element="element"
+                :index="index"
+                :active-id="activeId"
+                :form-conf="formConf"
+                @activeItem="activeFormItem"
+                @copyItem="drawingItemCopy"
+                @deleteItem="drawingItemDelete"
+              />
+            </draggable>
+            <div v-show="!drawingList.length" class="empty-info">
+              浠庡乏渚ф嫋鍏ユ垨鐐归�夌粍浠惰繘琛岃〃鍗曡璁�
+            </div>
+          </el-form>
+        </el-row>
+      </el-scrollbar>
+    </div>
+
+    <right-panel
+      :active-data="activeData"
+      :form-conf="formConf"
+      :show-field="!!drawingList.length"
+      @tag-change="tagChange"
+    />
+
+    <code-type-dialog
+      :visible.sync="dialogVisible"
+      title="閫夋嫨鐢熸垚绫诲瀷"
+      :show-file-name="showFileName"
+      @confirm="generate"
+    />
+    <input id="copyNode" type="hidden">
+  </div>
+</template>
+
+<script>
+import draggable from 'vuedraggable'
+import beautifier from 'js-beautify'
+import ClipboardJS from 'clipboard'
+import render from '@/utils/generator/render'
+import RightPanel from './RightPanel'
+import { inputComponents, selectComponents, layoutComponents, formConf } from '@/utils/generator/config'
+import { beautifierConf, titleCase } from '@/utils/index'
+import { makeUpHtml, vueTemplate, vueScript, cssStyle } from '@/utils/generator/html'
+import { makeUpJs } from '@/utils/generator/js'
+import { makeUpCss } from '@/utils/generator/css'
+import drawingDefault from '@/utils/generator/drawingDefault'
+import logo from '@/assets/logo/logo.png'
+import CodeTypeDialog from './CodeTypeDialog'
+import DraggableItem from './DraggableItem'
+
+let oldActiveId
+let tempActiveData
+
+export default {
+  components: {
+    draggable,
+    render,
+    RightPanel,
+    CodeTypeDialog,
+    DraggableItem
+  },
+  data() {
+    return {
+      logo,
+      idGlobal: 100,
+      formConf,
+      inputComponents,
+      selectComponents,
+      layoutComponents,
+      labelWidth: 100,
+      drawingList: drawingDefault,
+      drawingData: {},
+      activeId: drawingDefault[0].formId,
+      drawerVisible: false,
+      formData: {},
+      dialogVisible: false,
+      generateConf: null,
+      showFileName: false,
+      activeData: drawingDefault[0]
+    }
+  },
+  created() {
+    // 闃叉 firefox 涓� 鎷栨嫿 浼氭柊鎵撳崱涓�涓�夐」鍗�
+    document.body.ondrop = event => {
+      event.preventDefault()
+      event.stopPropagation()
+    }
+  },
+  watch: {
+    // eslint-disable-next-line func-names
+    'activeData.label': function (val, oldVal) {
+      if (
+        this.activeData.placeholder === undefined
+        || !this.activeData.tag
+        || oldActiveId !== this.activeId
+      ) {
+        return
+      }
+      this.activeData.placeholder = this.activeData.placeholder.replace(oldVal, '') + val
+    },
+    activeId: {
+      handler(val) {
+        oldActiveId = val
+      },
+      immediate: true
+    }
+  },
+  mounted() {
+    const clipboard = new ClipboardJS('#copyNode', {
+      text: trigger => {
+        const codeStr = this.generateCode()
+        this.$notify({
+          title: '鎴愬姛',
+          message: '浠g爜宸插鍒跺埌鍓垏鏉匡紝鍙矘璐淬��',
+          type: 'success'
+        })
+        return codeStr
+      }
+    })
+    clipboard.on('error', e => {
+      this.$message.error('浠g爜澶嶅埗澶辫触')
+    })
+  },
+  methods: {
+    activeFormItem(element) {
+      this.activeData = element
+      this.activeId = element.formId
+    },
+    onEnd(obj, a) {
+      if (obj.from !== obj.to) {
+        this.activeData = tempActiveData
+        this.activeId = this.idGlobal
+      }
+    },
+    addComponent(item) {
+      const clone = this.cloneComponent(item)
+      this.drawingList.push(clone)
+      this.activeFormItem(clone)
+    },
+    cloneComponent(origin) {
+      const clone = JSON.parse(JSON.stringify(origin))
+      clone.formId = ++this.idGlobal
+      clone.span = formConf.span
+      clone.renderKey = +new Date() // 鏀瑰彉renderKey鍚庡彲浠ュ疄鐜板己鍒舵洿鏂扮粍浠�
+      if (!clone.layout) clone.layout = 'colFormItem'
+      if (clone.layout === 'colFormItem') {
+        clone.vModel = `field${this.idGlobal}`
+        clone.placeholder !== undefined && (clone.placeholder += clone.label)
+        tempActiveData = clone
+      } else if (clone.layout === 'rowFormItem') {
+        delete clone.label
+        clone.componentName = `row${this.idGlobal}`
+        clone.gutter = this.formConf.gutter
+        tempActiveData = clone
+      }
+      return tempActiveData
+    },
+    AssembleFormData() {
+      this.formData = {
+        fields: JSON.parse(JSON.stringify(this.drawingList)),
+        ...this.formConf
+      }
+    },
+    generate(data) {
+      const func = this[`exec${titleCase(this.operationType)}`]
+      this.generateConf = data
+      func && func(data)
+    },
+    execRun(data) {
+      this.AssembleFormData()
+      this.drawerVisible = true
+    },
+    execDownload(data) {
+      const codeStr = this.generateCode()
+      const blob = new Blob([codeStr], { type: 'text/plain;charset=utf-8' })
+      this.$download.saveAs(blob, data.fileName)
+    },
+    execCopy(data) {
+      document.getElementById('copyNode').click()
+    },
+    empty() {
+      this.$confirm('纭畾瑕佹竻绌烘墍鏈夌粍浠跺悧锛�', '鎻愮ず', { type: 'warning' }).then(
+        () => {
+          this.drawingList = []
+        }
+      )
+    },
+    drawingItemCopy(item, parent) {
+      let clone = JSON.parse(JSON.stringify(item))
+      clone = this.createIdAndKey(clone)
+      parent.push(clone)
+      this.activeFormItem(clone)
+    },
+    createIdAndKey(item) {
+      item.formId = ++this.idGlobal
+      item.renderKey = +new Date()
+      if (item.layout === 'colFormItem') {
+        item.vModel = `field${this.idGlobal}`
+      } else if (item.layout === 'rowFormItem') {
+        item.componentName = `row${this.idGlobal}`
+      }
+      if (Array.isArray(item.children)) {
+        item.children = item.children.map(childItem => this.createIdAndKey(childItem))
+      }
+      return item
+    },
+    drawingItemDelete(index, parent) {
+      parent.splice(index, 1)
+      this.$nextTick(() => {
+        const len = this.drawingList.length
+        if (len) {
+          this.activeFormItem(this.drawingList[len - 1])
+        }
+      })
+    },
+    generateCode() {
+      const { type } = this.generateConf
+      this.AssembleFormData()
+      const script = vueScript(makeUpJs(this.formData, type))
+      const html = vueTemplate(makeUpHtml(this.formData, type))
+      const css = cssStyle(makeUpCss(this.formData))
+      return beautifier.html(html + script + css, beautifierConf.html)
+    },
+    download() {
+      this.dialogVisible = true
+      this.showFileName = true
+      this.operationType = 'download'
+    },
+    run() {
+      this.dialogVisible = true
+      this.showFileName = false
+      this.operationType = 'run'
+    },
+    copy() {
+      this.dialogVisible = true
+      this.showFileName = false
+      this.operationType = 'copy'
+    },
+    tagChange(newTag) {
+      newTag = this.cloneComponent(newTag)
+      newTag.vModel = this.activeData.vModel
+      newTag.formId = this.activeId
+      newTag.span = this.activeData.span
+      delete this.activeData.tag
+      delete this.activeData.tagIcon
+      delete this.activeData.document
+      Object.keys(newTag).forEach(key => {
+        if (this.activeData[key] !== undefined
+          && typeof this.activeData[key] === typeof newTag[key]) {
+          newTag[key] = this.activeData[key]
+        }
+      })
+      this.activeData = newTag
+      this.updateDrawingList(newTag, this.drawingList)
+    },
+    updateDrawingList(newTag, list) {
+      const index = list.findIndex(item => item.formId === this.activeId)
+      if (index > -1) {
+        list.splice(index, 1, newTag)
+      } else {
+        list.forEach(item => {
+          if (Array.isArray(item.children)) this.updateDrawingList(newTag, item.children)
+        })
+      }
+    }
+  }
+}
+</script>
+
+<style lang='scss'>
+.editor-tabs{
+  background: #121315;
+  .el-tabs__header{
+    margin: 0;
+    border-bottom-color: #121315;
+    .el-tabs__nav{
+      border-color: #121315;
+    }
+  }
+  .el-tabs__item{
+    height: 32px;
+    line-height: 32px;
+    color: #888a8e;
+    border-left: 1px solid #121315 !important;
+    background: #363636;
+    margin-right: 5px;
+    user-select: none;
+  }
+  .el-tabs__item.is-active{
+    background: #1e1e1e;
+    border-bottom-color: #1e1e1e!important;
+    color: #fff;
+  }
+  .el-icon-edit{
+    color: #f1fa8c;
+  }
+  .el-icon-document{
+    color: #a95812;
+  }
+}
+
+// home
+.right-scrollbar {
+  .el-scrollbar__view {
+    padding: 12px 18px 15px 15px;
+  }
+}
+.left-scrollbar .el-scrollbar__wrap {
+  box-sizing: border-box;
+  overflow-x: hidden !important;
+  margin-bottom: 0 !important;
+}
+.center-tabs{
+  .el-tabs__header{
+    margin-bottom: 0!important;
+  }
+  .el-tabs__item{
+    width: 50%;
+    text-align: center;
+  }
+  .el-tabs__nav{
+    width: 100%;
+  }
+}
+.reg-item{
+  padding: 12px 6px;
+  background: #f8f8f8;
+  position: relative;
+  border-radius: 4px;
+  .close-btn{
+    position: absolute;
+    right: -6px;
+    top: -6px;
+    display: block;
+    width: 16px;
+    height: 16px;
+    line-height: 16px;
+    background: rgba(0, 0, 0, 0.2);
+    border-radius: 50%;
+    color: #fff;
+    text-align: center;
+    z-index: 1;
+    cursor: pointer;
+    font-size: 12px;
+    &:hover{
+      background: rgba(210, 23, 23, 0.5)
+    }
+  }
+  & + .reg-item{
+    margin-top: 18px;
+  }
+}
+.action-bar{
+  & .el-button+.el-button {
+    margin-left: 15px;
+  }
+  & i {
+    font-size: 20px;
+    vertical-align: middle;
+    position: relative;
+    top: -1px;
+  }
+}
+
+.custom-tree-node{
+  width: 100%;
+  font-size: 14px;
+  .node-operation{
+    float: right;
+  }
+  i[class*="el-icon"] + i[class*="el-icon"]{
+    margin-left: 6px;
+  }
+  .el-icon-plus{
+    color: #409EFF;
+  }
+  .el-icon-delete{
+    color: #157a0c;
+  }
+}
+
+.left-scrollbar .el-scrollbar__view{
+  overflow-x: hidden;
+}
+
+.el-rate{
+  display: inline-block;
+  vertical-align: text-top;
+}
+.el-upload__tip{
+  line-height: 1.2;
+}
+
+$selectedColor: #f6f7ff;
+$lighterBlue: #409EFF;
+
+.container {
+  position: relative;
+  width: 100%;
+  height: 100%;
+}
+
+.components-list {
+  padding: 8px;
+  box-sizing: border-box;
+  height: 100%;
+  .components-item {
+    display: inline-block;
+    width: 48%;
+    margin: 1%;
+    transition: transform 0ms !important;
+  }
+}
+.components-draggable{
+  padding-bottom: 20px;
+}
+.components-title{
+  font-size: 14px;
+  color: #222;
+  margin: 6px 2px;
+  .svg-icon{
+    color: #666;
+    font-size: 18px;
+  }
+}
+
+.components-body {
+  padding: 8px 10px;
+  background: $selectedColor;
+  font-size: 12px;
+  cursor: move;
+  border: 1px dashed $selectedColor;
+  border-radius: 3px;
+  .svg-icon{
+    color: #777;
+    font-size: 15px;
+  }
+  &:hover {
+    border: 1px dashed #787be8;
+    color: #787be8;
+    .svg-icon {
+      color: #787be8;
+    }
+  }
+}
+
+.left-board {
+  width: 260px;
+  position: absolute;
+  left: 0;
+  top: 0;
+  height: 100vh;
+}
+.left-scrollbar{
+  height: calc(100vh - 42px);
+  overflow: hidden;
+}
+.center-scrollbar {
+  height: calc(100vh - 42px);
+  overflow: hidden;
+  border-left: 1px solid #f1e8e8;
+  border-right: 1px solid #f1e8e8;
+  box-sizing: border-box;
+}
+.center-board {
+  height: 100vh;
+  width: auto;
+  margin: 0 350px 0 260px;
+  box-sizing: border-box;
+}
+.empty-info{
+  position: absolute;
+  top: 46%;
+  left: 0;
+  right: 0;
+  text-align: center;
+  font-size: 18px;
+  color: #ccb1ea;
+  letter-spacing: 4px;
+}
+.action-bar{
+  position: relative;
+  height: 42px;
+  text-align: right;
+  padding: 0 15px;
+  box-sizing: border-box;;
+  border: 1px solid #f1e8e8;
+  border-top: none;
+  border-left: none;
+  .delete-btn{
+    color: #F56C6C;
+  }
+}
+.logo-wrapper{
+  position: relative;
+  height: 42px;
+  background: #fff;
+  border-bottom: 1px solid #f1e8e8;
+  box-sizing: border-box;
+}
+.logo{
+  position: absolute;
+  left: 12px;
+  top: 6px;
+  line-height: 30px;
+  color: #00afff;
+  font-weight: 600;
+  font-size: 17px;
+  white-space: nowrap;
+  > img{
+    width: 30px;
+    height: 30px;
+    vertical-align: top;
+  }
+  .github{
+    display: inline-block;
+    vertical-align: sub;
+    margin-left: 15px;
+    > img{
+      height: 22px;
+    }
+  }
+}
+
+.center-board-row {
+  padding: 12px 12px 15px 12px;
+  box-sizing: border-box;
+  & > .el-form {
+    // 69 = 12+15+42
+    height: calc(100vh - 69px);
+  }
+}
+.drawing-board {
+  height: 100%;
+  position: relative;
+  .components-body {
+    padding: 0;
+    margin: 0;
+    font-size: 0;
+  }
+  .sortable-ghost {
+    position: relative;
+    display: block;
+    overflow: hidden;
+    &::before {
+      content: " ";
+      position: absolute;
+      left: 0;
+      right: 0;
+      top: 0;
+      height: 3px;
+      background: rgb(89, 89, 223);
+      z-index: 2;
+    }
+  }
+  .components-item.sortable-ghost {
+    width: 100%;
+    height: 60px;
+    background-color: $selectedColor;
+  }
+  .active-from-item {
+    & > .el-form-item{
+      background: $selectedColor;
+      border-radius: 6px;
+    }
+    & > .drawing-item-copy, & > .drawing-item-delete{
+      display: initial;
+    }
+    & > .component-name{
+      color: $lighterBlue;
+    }
+  }
+  .el-form-item{
+    margin-bottom: 15px;
+  }
+}
+.drawing-item{
+  position: relative;
+  cursor: move;
+  &.unfocus-bordered:not(.activeFromItem) > div:first-child  {
+    border: 1px dashed #ccc;
+  }
+  .el-form-item{
+    padding: 12px 10px;
+  }
+}
+.drawing-row-item{
+  position: relative;
+  cursor: move;
+  box-sizing: border-box;
+  border: 1px dashed #ccc;
+  border-radius: 3px;
+  padding: 0 2px;
+  margin-bottom: 15px;
+  .drawing-row-item {
+    margin-bottom: 2px;
+  }
+  .el-col{
+    margin-top: 22px;
+  }
+  .el-form-item{
+    margin-bottom: 0;
+  }
+  .drag-wrapper{
+    min-height: 80px;
+  }
+  &.active-from-item{
+    border: 1px dashed $lighterBlue;
+  }
+  .component-name{
+    position: absolute;
+    top: 0;
+    left: 0;
+    font-size: 12px;
+    color: #bbb;
+    display: inline-block;
+    padding: 0 6px;
+  }
+}
+.drawing-item, .drawing-row-item{
+  &:hover {
+    & > .el-form-item{
+      background: $selectedColor;
+      border-radius: 6px;
+    }
+    & > .drawing-item-copy, & > .drawing-item-delete{
+      display: initial;
+    }
+  }
+  & > .drawing-item-copy, & > .drawing-item-delete{
+    display: none;
+    position: absolute;
+    top: -10px;
+    width: 22px;
+    height: 22px;
+    line-height: 22px;
+    text-align: center;
+    border-radius: 50%;
+    font-size: 12px;
+    border: 1px solid;
+    cursor: pointer;
+    z-index: 1;
+  }
+  & > .drawing-item-copy{
+    right: 56px;
+    border-color: $lighterBlue;
+    color: $lighterBlue;
+    background: #fff;
+    &:hover{
+      background: $lighterBlue;
+      color: #fff;
+    }
+  }
+  & > .drawing-item-delete{
+    right: 24px;
+    border-color: #F56C6C;
+    color: #F56C6C;
+    background: #fff;
+    &:hover{
+      background: #F56C6C;
+      color: #fff;
+    }
+  }
+}
+</style>
diff --git a/jcdm-ui/src/views/tool/gen/basicInfoForm.vue b/jcdm-ui/src/views/tool/gen/basicInfoForm.vue
new file mode 100644
index 0000000..7029529
--- /dev/null
+++ b/jcdm-ui/src/views/tool/gen/basicInfoForm.vue
@@ -0,0 +1,60 @@
+<template>
+  <el-form ref="basicInfoForm" :model="info" :rules="rules" label-width="150px">
+    <el-row>
+      <el-col :span="12">
+        <el-form-item label="琛ㄥ悕绉�" prop="tableName">
+          <el-input placeholder="璇疯緭鍏ヤ粨搴撳悕绉�" v-model="info.tableName" />
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="琛ㄦ弿杩�" prop="tableComment">
+          <el-input placeholder="璇疯緭鍏�" v-model="info.tableComment" />
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="瀹炰綋绫诲悕绉�" prop="className">
+          <el-input placeholder="璇疯緭鍏�" v-model="info.className" />
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="浣滆��" prop="functionAuthor">
+          <el-input placeholder="璇疯緭鍏�" v-model="info.functionAuthor" />
+        </el-form-item>
+      </el-col>
+      <el-col :span="24">
+        <el-form-item label="澶囨敞" prop="remark">
+          <el-input type="textarea" :rows="3" v-model="info.remark"></el-input>
+        </el-form-item>
+      </el-col>
+    </el-row>
+  </el-form>
+</template>
+
+<script>
+export default {
+  props: {
+    info: {
+      type: Object,
+      default: null
+    }
+  },
+  data() {
+    return {
+      rules: {
+        tableName: [
+          { required: true, message: "璇疯緭鍏ヨ〃鍚嶇О", trigger: "blur" }
+        ],
+        tableComment: [
+          { required: true, message: "璇疯緭鍏ヨ〃鎻忚堪", trigger: "blur" }
+        ],
+        className: [
+          { required: true, message: "璇疯緭鍏ュ疄浣撶被鍚嶇О", trigger: "blur" }
+        ],
+        functionAuthor: [
+          { required: true, message: "璇疯緭鍏ヤ綔鑰�", trigger: "blur" }
+        ]
+      }
+    };
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/tool/gen/editTable.vue b/jcdm-ui/src/views/tool/gen/editTable.vue
new file mode 100644
index 0000000..951497a
--- /dev/null
+++ b/jcdm-ui/src/views/tool/gen/editTable.vue
@@ -0,0 +1,234 @@
+<template>
+  <el-card>
+    <el-tabs v-model="activeName">
+      <el-tab-pane label="鍩烘湰淇℃伅" name="basic">
+        <basic-info-form ref="basicInfo" :info="info" />
+      </el-tab-pane>
+      <el-tab-pane label="瀛楁淇℃伅" name="columnInfo">
+        <el-table ref="dragTable" :data="columns" row-key="columnId" :max-height="tableHeight">
+          <el-table-column label="搴忓彿" type="index" min-width="5%" class-name="allowDrag" />
+          <el-table-column
+            label="瀛楁鍒楀悕"
+            prop="columnName"
+            min-width="10%"
+            :show-overflow-tooltip="true"
+          />
+          <el-table-column label="瀛楁鎻忚堪" min-width="10%">
+            <template slot-scope="scope">
+              <el-input v-model="scope.row.columnComment"></el-input>
+            </template>
+          </el-table-column>
+          <el-table-column
+            label="鐗╃悊绫诲瀷"
+            prop="columnType"
+            min-width="10%"
+            :show-overflow-tooltip="true"
+          />
+          <el-table-column label="Java绫诲瀷" min-width="11%">
+            <template slot-scope="scope">
+              <el-select v-model="scope.row.javaType">
+                <el-option label="Long" value="Long" />
+                <el-option label="String" value="String" />
+                <el-option label="Integer" value="Integer" />
+                <el-option label="Double" value="Double" />
+                <el-option label="BigDecimal" value="BigDecimal" />
+                <el-option label="Date" value="Date" />
+                <el-option label="Boolean" value="Boolean" />
+              </el-select>
+            </template>
+          </el-table-column>
+          <el-table-column label="java灞炴��" min-width="10%">
+            <template slot-scope="scope">
+              <el-input v-model="scope.row.javaField"></el-input>
+            </template>
+          </el-table-column>
+
+          <el-table-column label="鎻掑叆" min-width="5%">
+            <template slot-scope="scope">
+              <el-checkbox true-label="1" false-label="0" v-model="scope.row.isInsert"></el-checkbox>
+            </template>
+          </el-table-column>
+          <el-table-column label="缂栬緫" min-width="5%">
+            <template slot-scope="scope">
+              <el-checkbox true-label="1" false-label="0" v-model="scope.row.isEdit"></el-checkbox>
+            </template>
+          </el-table-column>
+          <el-table-column label="鍒楄〃" min-width="5%">
+            <template slot-scope="scope">
+              <el-checkbox true-label="1" false-label="0" v-model="scope.row.isList"></el-checkbox>
+            </template>
+          </el-table-column>
+          <el-table-column label="鏌ヨ" min-width="5%">
+            <template slot-scope="scope">
+              <el-checkbox true-label="1" false-label="0" v-model="scope.row.isQuery"></el-checkbox>
+            </template>
+          </el-table-column>
+          <el-table-column label="鏌ヨ鏂瑰紡" min-width="10%">
+            <template slot-scope="scope">
+              <el-select v-model="scope.row.queryType">
+                <el-option label="=" value="EQ" />
+                <el-option label="!=" value="NE" />
+                <el-option label=">" value="GT" />
+                <el-option label=">=" value="GTE" />
+                <el-option label="<" value="LT" />
+                <el-option label="<=" value="LTE" />
+                <el-option label="LIKE" value="LIKE" />
+                <el-option label="BETWEEN" value="BETWEEN" />
+              </el-select>
+            </template>
+          </el-table-column>
+          <el-table-column label="蹇呭~" min-width="5%">
+            <template slot-scope="scope">
+              <el-checkbox true-label="1" false-label="0" v-model="scope.row.isRequired"></el-checkbox>
+            </template>
+          </el-table-column>
+          <el-table-column label="鏄剧ず绫诲瀷" min-width="12%">
+            <template slot-scope="scope">
+              <el-select v-model="scope.row.htmlType">
+                <el-option label="鏂囨湰妗�" value="input" />
+                <el-option label="鏂囨湰鍩�" value="textarea" />
+                <el-option label="涓嬫媺妗�" value="select" />
+                <el-option label="鍗曢�夋" value="radio" />
+                <el-option label="澶嶉�夋" value="checkbox" />
+                <el-option label="鏃ユ湡鎺т欢" value="datetime" />
+                <el-option label="鍥剧墖涓婁紶" value="imageUpload" />
+                <el-option label="鏂囦欢涓婁紶" value="fileUpload" />
+                <el-option label="瀵屾枃鏈帶浠�" value="editor" />
+              </el-select>
+            </template>
+          </el-table-column>
+          <el-table-column label="瀛楀吀绫诲瀷" min-width="12%">
+            <template slot-scope="scope">
+              <el-select v-model="scope.row.dictType" clearable filterable placeholder="璇烽�夋嫨">
+                <el-option
+                  v-for="dict in dictOptions"
+                  :key="dict.dictType"
+                  :label="dict.dictName"
+                  :value="dict.dictType">
+                  <span style="float: left">{{ dict.dictName }}</span>
+                  <span style="float: right; color: #8492a6; font-size: 13px">{{ dict.dictType }}</span>
+              </el-option>
+              </el-select>
+            </template>
+          </el-table-column>
+        </el-table>
+      </el-tab-pane>
+      <el-tab-pane label="鐢熸垚淇℃伅" name="genInfo">
+        <gen-info-form ref="genInfo" :info="info" :tables="tables" :menus="menus"/>
+      </el-tab-pane>
+    </el-tabs>
+    <el-form label-width="100px">
+      <el-form-item style="text-align: center;margin-left:-100px;margin-top:10px;">
+        <el-button type="primary" @click="submitForm()">鎻愪氦</el-button>
+        <el-button @click="close()">杩斿洖</el-button>
+      </el-form-item>
+    </el-form>
+  </el-card>
+</template>
+
+<script>
+import { getGenTable, updateGenTable } from "@/api/tool/gen";
+import { optionselect as getDictOptionselect } from "@/api/system/dict/type";
+import { listMenu as getMenuTreeselect } from "@/api/system/menu";
+import basicInfoForm from "./basicInfoForm";
+import genInfoForm from "./genInfoForm";
+import Sortable from 'sortablejs'
+
+export default {
+  name: "GenEdit",
+  components: {
+    basicInfoForm,
+    genInfoForm
+  },
+  data() {
+    return {
+      // 閫変腑閫夐」鍗$殑 name
+      activeName: "columnInfo",
+      // 琛ㄦ牸鐨勯珮搴�
+      tableHeight: document.documentElement.scrollHeight - 245 + "px",
+      // 琛ㄤ俊鎭�
+      tables: [],
+      // 琛ㄥ垪淇℃伅
+      columns: [],
+      // 瀛楀吀淇℃伅
+      dictOptions: [],
+      // 鑿滃崟淇℃伅
+      menus: [],
+      // 琛ㄨ缁嗕俊鎭�
+      info: {}
+    };
+  },
+  created() {
+    const tableId = this.$route.params && this.$route.params.tableId;
+    if (tableId) {
+      // 鑾峰彇琛ㄨ缁嗕俊鎭�
+      getGenTable(tableId).then(res => {
+        this.columns = res.data.rows;
+        this.info = res.data.info;
+        this.tables = res.data.tables;
+      });
+      /** 鏌ヨ瀛楀吀涓嬫媺鍒楄〃 */
+      getDictOptionselect().then(response => {
+        this.dictOptions = response.data;
+      });
+      /** 鏌ヨ鑿滃崟涓嬫媺鍒楄〃 */
+      getMenuTreeselect().then(response => {
+        this.menus = this.handleTree(response.data, "menuId");
+      });
+    }
+  },
+  methods: {
+    /** 鎻愪氦鎸夐挳 */
+    submitForm() {
+      const basicForm = this.$refs.basicInfo.$refs.basicInfoForm;
+      const genForm = this.$refs.genInfo.$refs.genInfoForm;
+      Promise.all([basicForm, genForm].map(this.getFormPromise)).then(res => {
+        const validateResult = res.every(item => !!item);
+        if (validateResult) {
+          const genTable = Object.assign({}, basicForm.model, genForm.model);
+          genTable.columns = this.columns;
+          genTable.params = {
+            treeCode: genTable.treeCode,
+            treeName: genTable.treeName,
+            treeParentCode: genTable.treeParentCode,
+            parentMenuId: genTable.parentMenuId
+          };
+          updateGenTable(genTable).then(res => {
+            this.$modal.msgSuccess(res.msg);
+            if (res.code === 200) {
+              this.close();
+            }
+          });
+        } else {
+          this.$modal.msgError("琛ㄥ崟鏍¢獙鏈�氳繃锛岃閲嶆柊妫�鏌ユ彁浜ゅ唴瀹�");
+        }
+      });
+    },
+    getFormPromise(form) {
+      return new Promise(resolve => {
+        form.validate(res => {
+          resolve(res);
+        });
+      });
+    },
+    /** 鍏抽棴鎸夐挳 */
+    close() {
+      const obj = { path: "/tool/gen", query: { t: Date.now(), pageNum: this.$route.query.pageNum } };
+      this.$tab.closeOpenPage(obj);
+    }
+  },
+  mounted() {
+    const el = this.$refs.dragTable.$el.querySelectorAll(".el-table__body-wrapper > table > tbody")[0];
+    const sortable = Sortable.create(el, {
+      handle: ".allowDrag",
+      onEnd: evt => {
+        const targetRow = this.columns.splice(evt.oldIndex, 1)[0];
+        this.columns.splice(evt.newIndex, 0, targetRow);
+        for (let index in this.columns) {
+          this.columns[index].sort = parseInt(index) + 1;
+        }
+      }
+    });
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/tool/gen/genInfoForm.vue b/jcdm-ui/src/views/tool/gen/genInfoForm.vue
new file mode 100644
index 0000000..2d415d4
--- /dev/null
+++ b/jcdm-ui/src/views/tool/gen/genInfoForm.vue
@@ -0,0 +1,312 @@
+<template>
+  <el-form ref="genInfoForm" :model="info" :rules="rules" label-width="150px">
+    <el-row>
+      <el-col :span="12">
+        <el-form-item prop="tplCategory">
+          <span slot="label">鐢熸垚妯℃澘</span>
+          <el-select v-model="info.tplCategory" @change="tplSelectChange">
+            <el-option label="鍗曡〃锛堝鍒犳敼鏌ワ級" value="crud" />
+            <el-option label="鏍戣〃锛堝鍒犳敼鏌ワ級" value="tree" />
+            <el-option label="涓诲瓙琛紙澧炲垹鏀规煡锛�" value="sub" />
+          </el-select>
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item prop="tplWebType">
+          <span slot="label">鍓嶇绫诲瀷</span>
+          <el-select v-model="info.tplWebType">
+            <el-option label="Vue2 Element UI 妯$増" value="element-ui" />
+            <el-option label="Vue3 Element Plus 妯$増" value="element-plus" />
+          </el-select>
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item prop="packageName">
+          <span slot="label">
+            鐢熸垚鍖呰矾寰�
+            <el-tooltip content="鐢熸垚鍦ㄥ摢涓猨ava鍖呬笅锛屼緥濡� com.jcdm.system" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <el-input v-model="info.packageName" />
+        </el-form-item>
+      </el-col>
+
+      <el-col :span="12">
+        <el-form-item prop="moduleName">
+          <span slot="label">
+            鐢熸垚妯″潡鍚�
+            <el-tooltip content="鍙悊瑙d负瀛愮郴缁熷悕锛屼緥濡� system" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <el-input v-model="info.moduleName" />
+        </el-form-item>
+      </el-col>
+
+      <el-col :span="12">
+        <el-form-item prop="businessName">
+          <span slot="label">
+            鐢熸垚涓氬姟鍚�
+            <el-tooltip content="鍙悊瑙d负鍔熻兘鑻辨枃鍚嶏紝渚嬪 user" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <el-input v-model="info.businessName" />
+        </el-form-item>
+      </el-col>
+
+      <el-col :span="12">
+        <el-form-item prop="functionName">
+          <span slot="label">
+            鐢熸垚鍔熻兘鍚�
+            <el-tooltip content="鐢ㄤ綔绫绘弿杩帮紝渚嬪 鐢ㄦ埛" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <el-input v-model="info.functionName" />
+        </el-form-item>
+      </el-col>
+
+      <el-col :span="12">
+        <el-form-item prop="genType">
+          <span slot="label">
+            鐢熸垚浠g爜鏂瑰紡
+            <el-tooltip content="榛樿涓簔ip鍘嬬缉鍖呬笅杞斤紝涔熷彲浠ヨ嚜瀹氫箟鐢熸垚璺緞" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <el-radio v-model="info.genType" label="0">zip鍘嬬缉鍖�</el-radio>
+          <el-radio v-model="info.genType" label="1">鑷畾涔夎矾寰�</el-radio>
+        </el-form-item>
+      </el-col>
+
+      <el-col :span="12">
+        <el-form-item>
+          <span slot="label">
+            涓婄骇鑿滃崟
+            <el-tooltip content="鍒嗛厤鍒版寚瀹氳彍鍗曚笅锛屼緥濡� 绯荤粺绠$悊" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <treeselect
+            :append-to-body="true"
+            v-model="info.parentMenuId"
+            :options="menus"
+            :normalizer="normalizer"
+            :show-count="true"
+            placeholder="璇烽�夋嫨绯荤粺鑿滃崟"
+          />
+        </el-form-item>
+      </el-col>
+
+      <el-col :span="24" v-if="info.genType == '1'">
+        <el-form-item prop="genPath">
+          <span slot="label">
+            鑷畾涔夎矾寰�
+            <el-tooltip content="濉啓纾佺洏缁濆璺緞锛岃嫢涓嶅~鍐欙紝鍒欑敓鎴愬埌褰撳墠Web椤圭洰涓�" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <el-input v-model="info.genPath">
+            <el-dropdown slot="append">
+              <el-button type="primary">
+                鏈�杩戣矾寰勫揩閫熼�夋嫨
+                <i class="el-icon-arrow-down el-icon--right"></i>
+              </el-button>
+              <el-dropdown-menu slot="dropdown">
+                <el-dropdown-item @click.native="info.genPath = '/'">鎭㈠榛樿鐨勭敓鎴愬熀纭�璺緞</el-dropdown-item>
+              </el-dropdown-menu>
+            </el-dropdown>
+          </el-input>
+        </el-form-item>
+      </el-col>
+    </el-row>
+
+    <el-row v-show="info.tplCategory == 'tree'">
+      <h4 class="form-header">鍏朵粬淇℃伅</h4>
+      <el-col :span="12">
+        <el-form-item>
+          <span slot="label">
+            鏍戠紪鐮佸瓧娈�
+            <el-tooltip content="鏍戞樉绀虹殑缂栫爜瀛楁鍚嶏紝 濡傦細dept_id" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <el-select v-model="info.treeCode" placeholder="璇烽�夋嫨">
+            <el-option
+              v-for="(column, index) in info.columns"
+              :key="index"
+              :label="column.columnName + '锛�' + column.columnComment"
+              :value="column.columnName"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item>
+          <span slot="label">
+            鏍戠埗缂栫爜瀛楁
+            <el-tooltip content="鏍戞樉绀虹殑鐖剁紪鐮佸瓧娈靛悕锛� 濡傦細parent_Id" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <el-select v-model="info.treeParentCode" placeholder="璇烽�夋嫨">
+            <el-option
+              v-for="(column, index) in info.columns"
+              :key="index"
+              :label="column.columnName + '锛�' + column.columnComment"
+              :value="column.columnName"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item>
+          <span slot="label">
+            鏍戝悕绉板瓧娈�
+            <el-tooltip content="鏍戣妭鐐圭殑鏄剧ず鍚嶇О瀛楁鍚嶏紝 濡傦細dept_name" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <el-select v-model="info.treeName" placeholder="璇烽�夋嫨">
+            <el-option
+              v-for="(column, index) in info.columns"
+              :key="index"
+              :label="column.columnName + '锛�' + column.columnComment"
+              :value="column.columnName"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+      </el-col>
+    </el-row>
+    <el-row v-show="info.tplCategory == 'sub'">
+      <h4 class="form-header">鍏宠仈淇℃伅</h4>
+      <el-col :span="12">
+        <el-form-item>
+          <span slot="label">
+            鍏宠仈瀛愯〃鐨勮〃鍚�
+            <el-tooltip content="鍏宠仈瀛愯〃鐨勮〃鍚嶏紝 濡傦細sys_user" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <el-select v-model="info.subTableName" placeholder="璇烽�夋嫨" @change="subSelectChange">
+            <el-option
+              v-for="(table, index) in tables"
+              :key="index"
+              :label="table.tableName + '锛�' + table.tableComment"
+              :value="table.tableName"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item>
+          <span slot="label">
+            瀛愯〃鍏宠仈鐨勫閿悕
+            <el-tooltip content="瀛愯〃鍏宠仈鐨勫閿悕锛� 濡傦細user_id" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <el-select v-model="info.subTableFkName" placeholder="璇烽�夋嫨">
+            <el-option
+              v-for="(column, index) in subColumns"
+              :key="index"
+              :label="column.columnName + '锛�' + column.columnComment"
+              :value="column.columnName"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+      </el-col>
+    </el-row>
+  </el-form>
+</template>
+
+<script>
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+
+export default {
+  components: { Treeselect },
+  props: {
+    info: {
+      type: Object,
+      default: null
+    },
+    tables: {
+      type: Array,
+      default: null
+    },
+    menus: {
+      type: Array,
+      default: []
+    },
+  },
+  data() {
+    return {
+      subColumns: [],
+      rules: {
+        tplCategory: [
+          { required: true, message: "璇烽�夋嫨鐢熸垚妯℃澘", trigger: "blur" }
+        ],
+        packageName: [
+          { required: true, message: "璇疯緭鍏ョ敓鎴愬寘璺緞", trigger: "blur" }
+        ],
+        moduleName: [
+          { required: true, message: "璇疯緭鍏ョ敓鎴愭ā鍧楀悕", trigger: "blur" }
+        ],
+        businessName: [
+          { required: true, message: "璇疯緭鍏ョ敓鎴愪笟鍔″悕", trigger: "blur" }
+        ],
+        functionName: [
+          { required: true, message: "璇疯緭鍏ョ敓鎴愬姛鑳藉悕", trigger: "blur" }
+        ],
+      }
+    };
+  },
+  watch: {
+    'info.subTableName': function(val) {
+      this.setSubTableColumns(val);
+    },
+    'info.tplWebType': function(val) {
+      if (val === '') {
+        this.info.tplWebType = "element-ui";
+      }
+    }
+  },
+  methods: {
+    /** 杞崲鑿滃崟鏁版嵁缁撴瀯 */
+    normalizer(node) {
+      if (node.children && !node.children.length) {
+        delete node.children;
+      }
+      return {
+        id: node.menuId,
+        label: node.menuName,
+        children: node.children
+      };
+    },
+    /** 閫夋嫨瀛愯〃鍚嶈Е鍙� */
+    subSelectChange(value) {
+      this.info.subTableFkName = '';
+    },
+    /** 閫夋嫨鐢熸垚妯℃澘瑙﹀彂 */
+    tplSelectChange(value) {
+      if(value !== 'sub') {
+        this.info.subTableName = '';
+        this.info.subTableFkName = '';
+      }
+    },
+    /** 璁剧疆鍏宠仈澶栭敭 */
+    setSubTableColumns(value) {
+      for (var item in this.tables) {
+        const name = this.tables[item].tableName;
+        if (value === name) {
+          this.subColumns = this.tables[item].columns;
+          break;
+        }
+      }
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/tool/gen/importTable.vue b/jcdm-ui/src/views/tool/gen/importTable.vue
new file mode 100644
index 0000000..3ea9532
--- /dev/null
+++ b/jcdm-ui/src/views/tool/gen/importTable.vue
@@ -0,0 +1,120 @@
+<template>
+  <!-- 瀵煎叆琛� -->
+  <el-dialog title="瀵煎叆琛�" :visible.sync="visible" width="800px" top="5vh" append-to-body>
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true">
+      <el-form-item label="琛ㄥ悕绉�" prop="tableName">
+        <el-input
+          v-model="queryParams.tableName"
+          placeholder="璇疯緭鍏ヨ〃鍚嶇О"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="琛ㄦ弿杩�" prop="tableComment">
+        <el-input
+          v-model="queryParams.tableComment"
+          placeholder="璇疯緭鍏ヨ〃鎻忚堪"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+    <el-row>
+      <el-table @row-click="clickRow" ref="table" :data="dbTableList" @selection-change="handleSelectionChange" height="260px">
+        <el-table-column type="selection" width="55"></el-table-column>
+        <el-table-column prop="tableName" label="琛ㄥ悕绉�" :show-overflow-tooltip="true"></el-table-column>
+        <el-table-column prop="tableComment" label="琛ㄦ弿杩�" :show-overflow-tooltip="true"></el-table-column>
+        <el-table-column prop="createTime" label="鍒涘缓鏃堕棿"></el-table-column>
+        <el-table-column prop="updateTime" label="鏇存柊鏃堕棿"></el-table-column>
+      </el-table>
+      <pagination
+        v-show="total>0"
+        :total="total"
+        :page.sync="queryParams.pageNum"
+        :limit.sync="queryParams.pageSize"
+        @pagination="getList"
+      />
+    </el-row>
+    <div slot="footer" class="dialog-footer">
+      <el-button type="primary" @click="handleImportTable">纭� 瀹�</el-button>
+      <el-button @click="visible = false">鍙� 娑�</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { listDbTable, importTable } from "@/api/tool/gen";
+export default {
+  data() {
+    return {
+      // 閬僵灞�
+      visible: false,
+      // 閫変腑鏁扮粍鍊�
+      tables: [],
+      // 鎬绘潯鏁�
+      total: 0,
+      // 琛ㄦ暟鎹�
+      dbTableList: [],
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        tableName: undefined,
+        tableComment: undefined
+      }
+    };
+  },
+  methods: {
+    // 鏄剧ず寮规
+    show() {
+      this.getList();
+      this.visible = true;
+    },
+    clickRow(row) {
+      this.$refs.table.toggleRowSelection(row);
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.tables = selection.map(item => item.tableName);
+    },
+    // 鏌ヨ琛ㄦ暟鎹�
+    getList() {
+      listDbTable(this.queryParams).then(res => {
+        if (res.code === 200) {
+          this.dbTableList = res.rows;
+          this.total = res.total;
+        }
+      });
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    /** 瀵煎叆鎸夐挳鎿嶄綔 */
+    handleImportTable() {
+      const tableNames = this.tables.join(",");
+      if (tableNames == "") {
+        this.$modal.msgError("璇烽�夋嫨瑕佸鍏ョ殑琛�");
+        return;
+      }
+      importTable({ tables: tableNames }).then(res => {
+        this.$modal.msgSuccess(res.msg);
+        if (res.code === 200) {
+          this.visible = false;
+          this.$emit("ok");
+        }
+      });
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/tool/gen/index.vue b/jcdm-ui/src/views/tool/gen/index.vue
new file mode 100644
index 0000000..9b1e989
--- /dev/null
+++ b/jcdm-ui/src/views/tool/gen/index.vue
@@ -0,0 +1,337 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="琛ㄥ悕绉�" prop="tableName">
+        <el-input
+          v-model="queryParams.tableName"
+          placeholder="璇疯緭鍏ヨ〃鍚嶇О"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="琛ㄦ弿杩�" prop="tableComment">
+        <el-input
+          v-model="queryParams.tableComment"
+          placeholder="璇疯緭鍏ヨ〃鎻忚堪"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="鍒涘缓鏃堕棿">
+        <el-date-picker
+          v-model="dateRange"
+          style="width: 240px"
+          value-format="yyyy-MM-dd"
+          type="daterange"
+          range-separator="-"
+          start-placeholder="寮�濮嬫棩鏈�"
+          end-placeholder="缁撴潫鏃ユ湡"
+        ></el-date-picker>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          @click="handleGenTable"
+          v-hasPermi="['tool:gen:code']"
+        >鐢熸垚</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="info"
+          plain
+          icon="el-icon-upload"
+          size="mini"
+          @click="openImportTable"
+          v-hasPermi="['tool:gen:import']"
+        >瀵煎叆</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleEditTable"
+          v-hasPermi="['tool:gen:edit']"
+        >淇敼</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['tool:gen:remove']"
+        >鍒犻櫎</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="tableList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" align="center" width="55"></el-table-column>
+      <el-table-column label="搴忓彿" type="index" width="50" align="center">
+        <template slot-scope="scope">
+          <span>{{(queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column
+        label="琛ㄥ悕绉�"
+        align="center"
+        prop="tableName"
+        :show-overflow-tooltip="true"
+        width="120"
+      />
+      <el-table-column
+        label="琛ㄦ弿杩�"
+        align="center"
+        prop="tableComment"
+        :show-overflow-tooltip="true"
+        width="120"
+      />
+      <el-table-column
+        label="瀹炰綋"
+        align="center"
+        prop="className"
+        :show-overflow-tooltip="true"
+        width="120"
+      />
+      <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="160" />
+      <el-table-column label="鏇存柊鏃堕棿" align="center" prop="updateTime" width="160" />
+      <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            type="text"
+            size="small"
+            icon="el-icon-view"
+            @click="handlePreview(scope.row)"
+            v-hasPermi="['tool:gen:preview']"
+          >棰勮</el-button>
+          <el-button
+            type="text"
+            size="small"
+            icon="el-icon-edit"
+            @click="handleEditTable(scope.row)"
+            v-hasPermi="['tool:gen:edit']"
+          >缂栬緫</el-button>
+          <el-button
+            type="text"
+            size="small"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['tool:gen:remove']"
+          >鍒犻櫎</el-button>
+          <el-button
+            type="text"
+            size="small"
+            icon="el-icon-refresh"
+            @click="handleSynchDb(scope.row)"
+            v-hasPermi="['tool:gen:edit']"
+          >鍚屾</el-button>
+          <el-button
+            type="text"
+            size="small"
+            icon="el-icon-download"
+            @click="handleGenTable(scope.row)"
+            v-hasPermi="['tool:gen:code']"
+          >鐢熸垚浠g爜</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+    <!-- 棰勮鐣岄潰 -->
+    <el-dialog :title="preview.title" :visible.sync="preview.open" width="80%" top="5vh" append-to-body class="scrollbar">
+      <el-tabs v-model="preview.activeName">
+        <el-tab-pane
+          v-for="(value, key) in preview.data"
+          :label="key.substring(key.lastIndexOf('/')+1,key.indexOf('.vm'))"
+          :name="key.substring(key.lastIndexOf('/')+1,key.indexOf('.vm'))"
+          :key="key"
+        >
+          <el-link :underline="false" icon="el-icon-document-copy" v-clipboard:copy="value" v-clipboard:success="clipboardSuccess" style="float:right">澶嶅埗</el-link>
+          <pre><code class="hljs" v-html="highlightedCode(value, key)"></code></pre>
+        </el-tab-pane>
+      </el-tabs>
+    </el-dialog>
+    <import-table ref="import" @ok="handleQuery" />
+  </div>
+</template>
+
+<script>
+import { listTable, previewTable, delTable, genCode, synchDb } from "@/api/tool/gen";
+import importTable from "./importTable";
+import hljs from "highlight.js/lib/highlight";
+import "highlight.js/styles/github-gist.css";
+hljs.registerLanguage("java", require("highlight.js/lib/languages/java"));
+hljs.registerLanguage("xml", require("highlight.js/lib/languages/xml"));
+hljs.registerLanguage("html", require("highlight.js/lib/languages/xml"));
+hljs.registerLanguage("vue", require("highlight.js/lib/languages/xml"));
+hljs.registerLanguage("javascript", require("highlight.js/lib/languages/javascript"));
+hljs.registerLanguage("sql", require("highlight.js/lib/languages/sql"));
+
+export default {
+  name: "Gen",
+  components: { importTable },
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      // 鍞竴鏍囪瘑绗�
+      uniqueId: "",
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 閫変腑琛ㄦ暟缁�
+      tableNames: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 琛ㄦ暟鎹�
+      tableList: [],
+      // 鏃ユ湡鑼冨洿
+      dateRange: "",
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        tableName: undefined,
+        tableComment: undefined
+      },
+      // 棰勮鍙傛暟
+      preview: {
+        open: false,
+        title: "浠g爜棰勮",
+        data: {},
+        activeName: "domain.java"
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  activated() {
+    const time = this.$route.query.t;
+    if (time != null && time != this.uniqueId) {
+      this.uniqueId = time;
+      this.queryParams.pageNum = Number(this.$route.query.pageNum);
+      this.getList();
+    }
+  },
+  methods: {
+    /** 鏌ヨ琛ㄩ泦鍚� */
+    getList() {
+      this.loading = true;
+      listTable(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
+          this.tableList = response.rows;
+          this.total = response.total;
+          this.loading = false;
+        }
+      );
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 鐢熸垚浠g爜鎿嶄綔 */
+    handleGenTable(row) {
+      const tableNames = row.tableName || this.tableNames;
+      if (tableNames == "") {
+        this.$modal.msgError("璇烽�夋嫨瑕佺敓鎴愮殑鏁版嵁");
+        return;
+      }
+      if(row.genType === "1") {
+        genCode(row.tableName).then(response => {
+          this.$modal.msgSuccess("鎴愬姛鐢熸垚鍒拌嚜瀹氫箟璺緞锛�" + row.genPath);
+        });
+      } else {
+        this.$download.zip("/tool/gen/batchGenCode?tables=" + tableNames, "JCDM.zip");
+      }
+    },
+    /** 鍚屾鏁版嵁搴撴搷浣� */
+    handleSynchDb(row) {
+      const tableName = row.tableName;
+      this.$modal.confirm('纭瑕佸己鍒跺悓姝�"' + tableName + '"琛ㄧ粨鏋勫悧锛�').then(function() {
+        return synchDb(tableName);
+      }).then(() => {
+        this.$modal.msgSuccess("鍚屾鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 鎵撳紑瀵煎叆琛ㄥ脊绐� */
+    openImportTable() {
+      this.$refs.import.show();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.dateRange = [];
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    /** 棰勮鎸夐挳 */
+    handlePreview(row) {
+      previewTable(row.tableId).then(response => {
+        this.preview.data = response.data;
+        this.preview.open = true;
+        this.preview.activeName = "domain.java";
+      });
+    },
+    /** 楂樹寒鏄剧ず */
+    highlightedCode(code, key) {
+      const vmName = key.substring(key.lastIndexOf("/") + 1, key.indexOf(".vm"));
+      var language = vmName.substring(vmName.indexOf(".") + 1, vmName.length);
+      const result = hljs.highlight(language, code || "", true);
+      return result.value || '&nbsp;';
+    },
+    /** 澶嶅埗浠g爜鎴愬姛 */
+    clipboardSuccess() {
+      this.$modal.msgSuccess("澶嶅埗鎴愬姛");
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.tableId);
+      this.tableNames = selection.map(item => item.tableName);
+      this.single = selection.length != 1;
+      this.multiple = !selection.length;
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleEditTable(row) {
+      const tableId = row.tableId || this.ids[0];
+      const tableName = row.tableName || this.tableNames[0];
+      const params = { pageNum: this.queryParams.pageNum };
+      this.$tab.openPage("淇敼[" + tableName + "]鐢熸垚閰嶇疆", '/tool/gen-edit/index/' + tableId, params);
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const tableIds = row.tableId || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎琛ㄧ紪鍙蜂负"' + tableIds + '"鐨勬暟鎹」锛�').then(function() {
+        return delTable(tableIds);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    }
+  }
+};
+</script>
diff --git a/jcdm-ui/src/views/tool/swagger/index.vue b/jcdm-ui/src/views/tool/swagger/index.vue
new file mode 100644
index 0000000..b8becc6
--- /dev/null
+++ b/jcdm-ui/src/views/tool/swagger/index.vue
@@ -0,0 +1,15 @@
+<template>
+  <i-frame :src="url" />
+</template>
+<script>
+import iFrame from "@/components/iFrame/index";
+export default {
+  name: "Swagger",
+  components: { iFrame },
+  data() {
+    return {
+      url: process.env.VUE_APP_BASE_API + "/swagger-ui/index.html"
+    };
+  },
+};
+</script>
diff --git a/jcdm-ui/vue.config.js b/jcdm-ui/vue.config.js
new file mode 100644
index 0000000..d22457d
--- /dev/null
+++ b/jcdm-ui/vue.config.js
@@ -0,0 +1,132 @@
+'use strict'
+const path = require('path')
+
+function resolve(dir) {
+  return path.join(__dirname, dir)
+}
+
+const CompressionPlugin = require('compression-webpack-plugin')
+
+const name = process.env.VUE_APP_TITLE || '姹熷MES绠$悊绯荤粺' // 缃戦〉鏍囬
+
+const port = process.env.port || process.env.npm_config_port || 80 // 绔彛
+
+// vue.config.js 閰嶇疆璇存槑
+//瀹樻柟vue.config.js 鍙傝�冩枃妗� https://cli.vuejs.org/zh/config/#css-loaderoptions
+// 杩欓噷鍙垪涓�閮ㄥ垎锛屽叿浣撻厤缃弬鑰冩枃妗�
+module.exports = {
+  // 閮ㄧ讲鐢熶骇鐜鍜屽紑鍙戠幆澧冧笅鐨刄RL銆�
+  // 榛樿鎯呭喌涓嬶紝Vue CLI 浼氬亣璁句綘鐨勫簲鐢ㄦ槸琚儴缃插湪涓�涓煙鍚嶇殑鏍硅矾寰勪笂
+  // 濡傛灉搴旂敤琚儴缃插湪涓�涓瓙璺緞涓婏紝浣犲氨闇�瑕佺敤杩欎釜閫夐」鎸囧畾杩欎釜瀛愯矾寰勩��
+  publicPath: process.env.NODE_ENV === "production" ? "/" : "/",
+  // 鍦╪pm run build 鎴� yarn build 鏃� 锛岀敓鎴愭枃浠剁殑鐩綍鍚嶇О锛堣鍜宐aseUrl鐨勭敓浜х幆澧冭矾寰勪竴鑷达級锛堥粯璁ist锛�
+  outputDir: 'dist',
+  // 鐢ㄤ簬鏀剧疆鐢熸垚鐨勯潤鎬佽祫婧� (js銆乧ss銆乮mg銆乫onts) 鐨勶紱锛堥」鐩墦鍖呬箣鍚庯紝闈欐�佽祫婧愪細鏀惧湪杩欎釜鏂囦欢澶逛笅锛�
+  assetsDir: 'static',
+  // 鏄惁寮�鍚痚slint淇濆瓨妫�娴嬶紝鏈夋晥鍊硷細ture | false | 'error'
+  lintOnSave: process.env.NODE_ENV === 'development',
+  // 濡傛灉浣犱笉闇�瑕佺敓浜х幆澧冪殑 source map锛屽彲浠ュ皢鍏惰缃负 false 浠ュ姞閫熺敓浜х幆澧冩瀯寤恒��
+  productionSourceMap: false,
+  // webpack-dev-server 鐩稿叧閰嶇疆
+  devServer: {
+    host: '0.0.0.0',
+    port: port,
+    open: true,
+    proxy: {
+      [process.env.VUE_APP_BASE_API]: {
+        target: `http://localhost:8080`,
+        changeOrigin: true,
+        pathRewrite: {
+          ['^' + process.env.VUE_APP_BASE_API]: ''
+        }
+      }
+    },
+    disableHostCheck: true
+  },
+  css: {
+    loaderOptions: {
+      sass: {
+        sassOptions: { outputStyle: "expanded" }
+      }
+    }
+  },
+  configureWebpack: {
+    name: name,
+    resolve: {
+      alias: {
+        '@': resolve('src')
+      }
+    },
+    plugins: [
+      new CompressionPlugin({
+        cache: false,                   // 涓嶅惎鐢ㄦ枃浠剁紦瀛�
+        test: /\.(js|css|html)?$/i,     // 鍘嬬缉鏂囦欢鏍煎紡
+        filename: '[path].gz[query]',   // 鍘嬬缉鍚庣殑鏂囦欢鍚�
+        algorithm: 'gzip',              // 浣跨敤gzip鍘嬬缉
+        minRatio: 0.8                   // 鍘嬬缉鐜囧皬浜�1鎵嶄細鍘嬬缉
+      })
+    ],
+  },
+  chainWebpack(config) {
+    config.plugins.delete('preload') // TODO: need test
+    config.plugins.delete('prefetch') // TODO: need test
+
+    // set svg-sprite-loader
+    config.module
+      .rule('svg')
+      .exclude.add(resolve('src/assets/icons'))
+      .end()
+    config.module
+      .rule('icons')
+      .test(/\.svg$/)
+      .include.add(resolve('src/assets/icons'))
+      .end()
+      .use('svg-sprite-loader')
+      .loader('svg-sprite-loader')
+      .options({
+        symbolId: 'icon-[name]'
+      })
+      .end()
+
+    config.when(process.env.NODE_ENV !== 'development', config => {
+          config
+            .plugin('ScriptExtHtmlWebpackPlugin')
+            .after('html')
+            .use('script-ext-html-webpack-plugin', [{
+            // `runtime` must same as runtimeChunk name. default is `runtime`
+              inline: /runtime\..*\.js$/
+            }])
+            .end()
+
+          config.optimization.splitChunks({
+            chunks: 'all',
+            cacheGroups: {
+              libs: {
+                name: 'chunk-libs',
+                test: /[\\/]node_modules[\\/]/,
+                priority: 10,
+                chunks: 'initial' // only package third parties that are initially dependent
+              },
+              elementUI: {
+                name: 'chunk-elementUI', // split elementUI into a single package
+                test: /[\\/]node_modules[\\/]_?element-ui(.*)/, // in order to adapt to cnpm
+                priority: 20 // the weight needs to be larger than libs and app or it will be packaged into libs or app
+              },
+              commons: {
+                name: 'chunk-commons',
+                test: resolve('src/components'), // can customize your rules
+                minChunks: 3, //  minimum common number
+                priority: 5,
+                reuseExistingChunk: true
+              }
+            }
+          })
+
+          config.optimization.runtimeChunk('single'),
+          {
+             from: path.resolve(__dirname, './public/robots.txt'), //闃茬埇铏枃浠�
+             to: './' //鍒版牴鐩綍涓�
+          }
+    })
+  }
+}
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..a52acb9
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,6 @@
+{
+  "name": "Jcdm-Mes",
+  "lockfileVersion": 2,
+  "requires": true,
+  "packages": {}
+}
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..6f32080
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,240 @@
+<?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>
+	
+    <groupId>com.jcdm</groupId>
+    <artifactId>jcdm</artifactId>
+    <version>3.8.6</version>
+
+    <name>jcdm</name>
+    <url>http://www.jcdm.vip</url>
+    <description>姹熷MES绠$悊绯荤粺</description>
+    
+    <properties>
+        <jcdm.version>3.8.6</jcdm.version>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <java.version>1.8</java.version>
+        <maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
+        <druid.version>1.2.16</druid.version>
+        <bitwalker.version>1.21</bitwalker.version>
+        <swagger.version>3.0.0</swagger.version>
+        <kaptcha.version>2.3.3</kaptcha.version>
+        <pagehelper.boot.version>1.4.6</pagehelper.boot.version>
+        <fastjson.version>2.0.41</fastjson.version>
+        <oshi.version>6.4.6</oshi.version>
+        <commons.io.version>2.13.0</commons.io.version>
+        <commons.collections.version>3.2.2</commons.collections.version>
+        <poi.version>4.1.2</poi.version>
+        <velocity.version>2.3</velocity.version>
+        <jwt.version>0.9.1</jwt.version>
+    </properties>
+
+    <!-- 渚濊禆澹版槑 -->
+    <dependencyManagement>
+        <dependencies>
+
+            <!-- SpringBoot鐨勪緷璧栭厤缃�-->
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-dependencies</artifactId>
+                <version>2.5.15</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+
+            <!-- 闃块噷鏁版嵁搴撹繛鎺ユ睜 -->
+            <dependency>
+                <groupId>com.alibaba</groupId>
+                <artifactId>druid-spring-boot-starter</artifactId>
+                <version>${druid.version}</version>
+            </dependency>
+
+            <!-- 瑙f瀽瀹㈡埛绔搷浣滅郴缁熴�佹祻瑙堝櫒绛� -->
+            <dependency>
+                <groupId>eu.bitwalker</groupId>
+                <artifactId>UserAgentUtils</artifactId>
+                <version>${bitwalker.version}</version>
+            </dependency>
+
+            <!-- pagehelper 鍒嗛〉鎻掍欢 -->
+            <dependency>
+                <groupId>com.github.pagehelper</groupId>
+                <artifactId>pagehelper-spring-boot-starter</artifactId>
+                <version>${pagehelper.boot.version}</version>
+            </dependency>
+
+            <!-- 鑾峰彇绯荤粺淇℃伅 -->
+            <dependency>
+                <groupId>com.github.oshi</groupId>
+                <artifactId>oshi-core</artifactId>
+                <version>${oshi.version}</version>
+            </dependency>
+
+            <!-- Swagger3渚濊禆 -->
+            <dependency>
+                <groupId>io.springfox</groupId>
+                <artifactId>springfox-boot-starter</artifactId>
+                <version>${swagger.version}</version>
+                <exclusions>
+                    <exclusion>
+                        <groupId>io.swagger</groupId>
+                        <artifactId>swagger-models</artifactId>
+                    </exclusion>
+                </exclusions>
+            </dependency>
+
+            <!-- io甯哥敤宸ュ叿绫� -->
+            <dependency>
+                <groupId>commons-io</groupId>
+                <artifactId>commons-io</artifactId>
+                <version>${commons.io.version}</version>
+            </dependency>
+
+            <!-- excel宸ュ叿 -->
+            <dependency>
+                <groupId>org.apache.poi</groupId>
+                <artifactId>poi-ooxml</artifactId>
+                <version>${poi.version}</version>
+            </dependency>
+
+            <!-- velocity浠g爜鐢熸垚浣跨敤妯℃澘 -->
+            <dependency>
+                <groupId>org.apache.velocity</groupId>
+                <artifactId>velocity-engine-core</artifactId>
+                <version>${velocity.version}</version>
+            </dependency>
+
+            <!-- collections宸ュ叿绫� -->
+            <dependency>
+                <groupId>commons-collections</groupId>
+                <artifactId>commons-collections</artifactId>
+                <version>${commons.collections.version}</version>
+            </dependency>
+
+            <!-- 闃块噷JSON瑙f瀽鍣� -->
+            <dependency>
+                <groupId>com.alibaba.fastjson2</groupId>
+                <artifactId>fastjson2</artifactId>
+                <version>${fastjson.version}</version>
+            </dependency>
+
+            <!-- Token鐢熸垚涓庤В鏋�-->
+            <dependency>
+                <groupId>io.jsonwebtoken</groupId>
+                <artifactId>jjwt</artifactId>
+                <version>${jwt.version}</version>
+            </dependency>
+
+            <!-- 楠岃瘉鐮� -->
+            <dependency>
+                <groupId>pro.fessional</groupId>
+                <artifactId>kaptcha</artifactId>
+                <version>${kaptcha.version}</version>
+            </dependency>
+
+            <!-- 瀹氭椂浠诲姟-->
+            <dependency>
+                <groupId>com.jcdm</groupId>
+                <artifactId>jcdm-quartz</artifactId>
+                <version>${jcdm.version}</version>
+            </dependency>
+
+            <!-- 浠g爜鐢熸垚-->
+            <dependency>
+                <groupId>com.jcdm</groupId>
+                <artifactId>jcdm-generator</artifactId>
+                <version>${jcdm.version}</version>
+            </dependency>
+
+            <!-- 鏍稿績妯″潡-->
+            <dependency>
+                <groupId>com.jcdm</groupId>
+                <artifactId>jcdm-framework</artifactId>
+                <version>${jcdm.version}</version>
+            </dependency>
+
+            <!-- 绯荤粺妯″潡-->
+            <dependency>
+                <groupId>com.jcdm</groupId>
+                <artifactId>jcdm-system</artifactId>
+                <version>${jcdm.version}</version>
+            </dependency>
+
+            <!-- 閫氱敤宸ュ叿-->
+            <dependency>
+                <groupId>com.jcdm</groupId>
+                <artifactId>jcdm-common</artifactId>
+                <version>${jcdm.version}</version>
+            </dependency>
+
+            <!-- JCDM妯″潡-->
+            <dependency>
+                <groupId>com.jcdm</groupId>
+                <artifactId>jcdm-main</artifactId>
+                <version>${jcdm.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>org.apache.commons</groupId>
+                <artifactId>commons-pool2</artifactId>
+                <version>2.12.0</version>
+            </dependency>
+
+        </dependencies>
+    </dependencyManagement>
+
+    <modules>
+        <module>jcdm-admin</module>
+        <module>jcdm-framework</module>
+        <module>jcdm-system</module>
+        <module>jcdm-quartz</module>
+        <module>jcdm-generator</module>
+        <module>jcdm-common</module>
+        <module>jcdm-main</module>
+    </modules>
+    <packaging>pom</packaging>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.1</version>
+                <configuration>
+                    <source>${java.version}</source>
+                    <target>${java.version}</target>
+                    <encoding>${project.build.sourceEncoding}</encoding>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <repositories>
+        <repository>
+            <id>public</id>
+            <name>aliyun nexus</name>
+            <url>https://maven.aliyun.com/repository/public</url>
+            <releases>
+                <enabled>true</enabled>
+            </releases>
+        </repository>
+    </repositories>
+
+    <pluginRepositories>
+        <pluginRepository>
+            <id>public</id>
+            <name>aliyun nexus</name>
+            <url>https://maven.aliyun.com/repository/public</url>
+            <releases>
+                <enabled>true</enabled>
+            </releases>
+            <snapshots>
+                <enabled>false</enabled>
+            </snapshots>
+        </pluginRepository>
+    </pluginRepositories>
+
+</project>
\ No newline at end of file
diff --git a/sql/quartz.sql b/sql/quartz.sql
new file mode 100644
index 0000000..cee613b
--- /dev/null
+++ b/sql/quartz.sql
@@ -0,0 +1,174 @@
+DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;
+DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;
+DROP TABLE IF EXISTS QRTZ_LOCKS;
+DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_JOB_DETAILS;
+DROP TABLE IF EXISTS QRTZ_CALENDARS;
+
+-- ----------------------------
+-- 1銆佸瓨鍌ㄦ瘡涓�涓凡閰嶇疆鐨� jobDetail 鐨勮缁嗕俊鎭�
+-- ----------------------------
+create table QRTZ_JOB_DETAILS (
+    sched_name           varchar(120)    not null            comment '璋冨害鍚嶇О',
+    job_name             varchar(200)    not null            comment '浠诲姟鍚嶇О',
+    job_group            varchar(200)    not null            comment '浠诲姟缁勫悕',
+    description          varchar(250)    null                comment '鐩稿叧浠嬬粛',
+    job_class_name       varchar(250)    not null            comment '鎵ц浠诲姟绫诲悕绉�',
+    is_durable           varchar(1)      not null            comment '鏄惁鎸佷箙鍖�',
+    is_nonconcurrent     varchar(1)      not null            comment '鏄惁骞跺彂',
+    is_update_data       varchar(1)      not null            comment '鏄惁鏇存柊鏁版嵁',
+    requests_recovery    varchar(1)      not null            comment '鏄惁鎺ュ彈鎭㈠鎵ц',
+    job_data             blob            null                comment '瀛樻斁鎸佷箙鍖杍ob瀵硅薄',
+    primary key (sched_name, job_name, job_group)
+) engine=innodb comment = '浠诲姟璇︾粏淇℃伅琛�';
+
+-- ----------------------------
+-- 2銆� 瀛樺偍宸查厤缃殑 Trigger 鐨勪俊鎭�
+-- ----------------------------
+create table QRTZ_TRIGGERS (
+    sched_name           varchar(120)    not null            comment '璋冨害鍚嶇О',
+    trigger_name         varchar(200)    not null            comment '瑙﹀彂鍣ㄧ殑鍚嶅瓧',
+    trigger_group        varchar(200)    not null            comment '瑙﹀彂鍣ㄦ墍灞炵粍鐨勫悕瀛�',
+    job_name             varchar(200)    not null            comment 'qrtz_job_details琛╦ob_name鐨勫閿�',
+    job_group            varchar(200)    not null            comment 'qrtz_job_details琛╦ob_group鐨勫閿�',
+    description          varchar(250)    null                comment '鐩稿叧浠嬬粛',
+    next_fire_time       bigint(13)      null                comment '涓婁竴娆¤Е鍙戞椂闂达紙姣锛�',
+    prev_fire_time       bigint(13)      null                comment '涓嬩竴娆¤Е鍙戞椂闂达紙榛樿涓�-1琛ㄧず涓嶈Е鍙戯級',
+    priority             integer         null                comment '浼樺厛绾�',
+    trigger_state        varchar(16)     not null            comment '瑙﹀彂鍣ㄧ姸鎬�',
+    trigger_type         varchar(8)      not null            comment '瑙﹀彂鍣ㄧ殑绫诲瀷',
+    start_time           bigint(13)      not null            comment '寮�濮嬫椂闂�',
+    end_time             bigint(13)      null                comment '缁撴潫鏃堕棿',
+    calendar_name        varchar(200)    null                comment '鏃ョ▼琛ㄥ悕绉�',
+    misfire_instr        smallint(2)     null                comment '琛ュ伩鎵ц鐨勭瓥鐣�',
+    job_data             blob            null                comment '瀛樻斁鎸佷箙鍖杍ob瀵硅薄',
+    primary key (sched_name, trigger_name, trigger_group),
+    foreign key (sched_name, job_name, job_group) references QRTZ_JOB_DETAILS(sched_name, job_name, job_group)
+) engine=innodb comment = '瑙﹀彂鍣ㄨ缁嗕俊鎭〃';
+
+-- ----------------------------
+-- 3銆� 瀛樺偍绠�鍗曠殑 Trigger锛屽寘鎷噸澶嶆鏁帮紝闂撮殧锛屼互鍙婂凡瑙﹀彂鐨勬鏁�
+-- ----------------------------
+create table QRTZ_SIMPLE_TRIGGERS (
+    sched_name           varchar(120)    not null            comment '璋冨害鍚嶇О',
+    trigger_name         varchar(200)    not null            comment 'qrtz_triggers琛╰rigger_name鐨勫閿�',
+    trigger_group        varchar(200)    not null            comment 'qrtz_triggers琛╰rigger_group鐨勫閿�',
+    repeat_count         bigint(7)       not null            comment '閲嶅鐨勬鏁扮粺璁�',
+    repeat_interval      bigint(12)      not null            comment '閲嶅鐨勯棿闅旀椂闂�',
+    times_triggered      bigint(10)      not null            comment '宸茬粡瑙﹀彂鐨勬鏁�',
+    primary key (sched_name, trigger_name, trigger_group),
+    foreign key (sched_name, trigger_name, trigger_group) references QRTZ_TRIGGERS(sched_name, trigger_name, trigger_group)
+) engine=innodb comment = '绠�鍗曡Е鍙戝櫒鐨勪俊鎭〃';
+
+-- ----------------------------
+-- 4銆� 瀛樺偍 Cron Trigger锛屽寘鎷� Cron 琛ㄨ揪寮忓拰鏃跺尯淇℃伅
+-- ---------------------------- 
+create table QRTZ_CRON_TRIGGERS (
+    sched_name           varchar(120)    not null            comment '璋冨害鍚嶇О',
+    trigger_name         varchar(200)    not null            comment 'qrtz_triggers琛╰rigger_name鐨勫閿�',
+    trigger_group        varchar(200)    not null            comment 'qrtz_triggers琛╰rigger_group鐨勫閿�',
+    cron_expression      varchar(200)    not null            comment 'cron琛ㄨ揪寮�',
+    time_zone_id         varchar(80)                         comment '鏃跺尯',
+    primary key (sched_name, trigger_name, trigger_group),
+    foreign key (sched_name, trigger_name, trigger_group) references QRTZ_TRIGGERS(sched_name, trigger_name, trigger_group)
+) engine=innodb comment = 'Cron绫诲瀷鐨勮Е鍙戝櫒琛�';
+
+-- ----------------------------
+-- 5銆� Trigger 浣滀负 Blob 绫诲瀷瀛樺偍(鐢ㄤ簬 Quartz 鐢ㄦ埛鐢� JDBC 鍒涘缓浠栦滑鑷繁瀹氬埗鐨� Trigger 绫诲瀷锛孞obStore 骞朵笉鐭ラ亾濡備綍瀛樺偍瀹炰緥鐨勬椂鍊�)
+-- ---------------------------- 
+create table QRTZ_BLOB_TRIGGERS (
+    sched_name           varchar(120)    not null            comment '璋冨害鍚嶇О',
+    trigger_name         varchar(200)    not null            comment 'qrtz_triggers琛╰rigger_name鐨勫閿�',
+    trigger_group        varchar(200)    not null            comment 'qrtz_triggers琛╰rigger_group鐨勫閿�',
+    blob_data            blob            null                comment '瀛樻斁鎸佷箙鍖朤rigger瀵硅薄',
+    primary key (sched_name, trigger_name, trigger_group),
+    foreign key (sched_name, trigger_name, trigger_group) references QRTZ_TRIGGERS(sched_name, trigger_name, trigger_group)
+) engine=innodb comment = 'Blob绫诲瀷鐨勮Е鍙戝櫒琛�';
+
+-- ----------------------------
+-- 6銆� 浠� Blob 绫诲瀷瀛樺偍瀛樻斁鏃ュ巻淇℃伅锛� quartz鍙厤缃竴涓棩鍘嗘潵鎸囧畾涓�涓椂闂磋寖鍥�
+-- ---------------------------- 
+create table QRTZ_CALENDARS (
+    sched_name           varchar(120)    not null            comment '璋冨害鍚嶇О',
+    calendar_name        varchar(200)    not null            comment '鏃ュ巻鍚嶇О',
+    calendar             blob            not null            comment '瀛樻斁鎸佷箙鍖朿alendar瀵硅薄',
+    primary key (sched_name, calendar_name)
+) engine=innodb comment = '鏃ュ巻淇℃伅琛�';
+
+-- ----------------------------
+-- 7銆� 瀛樺偍宸叉殏鍋滅殑 Trigger 缁勭殑淇℃伅
+-- ---------------------------- 
+create table QRTZ_PAUSED_TRIGGER_GRPS (
+    sched_name           varchar(120)    not null            comment '璋冨害鍚嶇О',
+    trigger_group        varchar(200)    not null            comment 'qrtz_triggers琛╰rigger_group鐨勫閿�',
+    primary key (sched_name, trigger_group)
+) engine=innodb comment = '鏆傚仠鐨勮Е鍙戝櫒琛�';
+
+-- ----------------------------
+-- 8銆� 瀛樺偍涓庡凡瑙﹀彂鐨� Trigger 鐩稿叧鐨勭姸鎬佷俊鎭紝浠ュ強鐩歌仈 Job 鐨勬墽琛屼俊鎭�
+-- ---------------------------- 
+create table QRTZ_FIRED_TRIGGERS (
+    sched_name           varchar(120)    not null            comment '璋冨害鍚嶇О',
+    entry_id             varchar(95)     not null            comment '璋冨害鍣ㄥ疄渚媔d',
+    trigger_name         varchar(200)    not null            comment 'qrtz_triggers琛╰rigger_name鐨勫閿�',
+    trigger_group        varchar(200)    not null            comment 'qrtz_triggers琛╰rigger_group鐨勫閿�',
+    instance_name        varchar(200)    not null            comment '璋冨害鍣ㄥ疄渚嬪悕',
+    fired_time           bigint(13)      not null            comment '瑙﹀彂鐨勬椂闂�',
+    sched_time           bigint(13)      not null            comment '瀹氭椂鍣ㄥ埗瀹氱殑鏃堕棿',
+    priority             integer         not null            comment '浼樺厛绾�',
+    state                varchar(16)     not null            comment '鐘舵��',
+    job_name             varchar(200)    null                comment '浠诲姟鍚嶇О',
+    job_group            varchar(200)    null                comment '浠诲姟缁勫悕',
+    is_nonconcurrent     varchar(1)      null                comment '鏄惁骞跺彂',
+    requests_recovery    varchar(1)      null                comment '鏄惁鎺ュ彈鎭㈠鎵ц',
+    primary key (sched_name, entry_id)
+) engine=innodb comment = '宸茶Е鍙戠殑瑙﹀彂鍣ㄨ〃';
+
+-- ----------------------------
+-- 9銆� 瀛樺偍灏戦噺鐨勬湁鍏� Scheduler 鐨勭姸鎬佷俊鎭紝鍋囧鏄敤浜庨泦缇や腑锛屽彲浠ョ湅鍒板叾浠栫殑 Scheduler 瀹炰緥
+-- ---------------------------- 
+create table QRTZ_SCHEDULER_STATE (
+    sched_name           varchar(120)    not null            comment '璋冨害鍚嶇О',
+    instance_name        varchar(200)    not null            comment '瀹炰緥鍚嶇О',
+    last_checkin_time    bigint(13)      not null            comment '涓婃妫�鏌ユ椂闂�',
+    checkin_interval     bigint(13)      not null            comment '妫�鏌ラ棿闅旀椂闂�',
+    primary key (sched_name, instance_name)
+) engine=innodb comment = '璋冨害鍣ㄧ姸鎬佽〃';
+
+-- ----------------------------
+-- 10銆� 瀛樺偍绋嬪簭鐨勬偛瑙傞攣鐨勪俊鎭�(鍋囧浣跨敤浜嗘偛瑙傞攣)
+-- ---------------------------- 
+create table QRTZ_LOCKS (
+    sched_name           varchar(120)    not null            comment '璋冨害鍚嶇О',
+    lock_name            varchar(40)     not null            comment '鎮茶閿佸悕绉�',
+    primary key (sched_name, lock_name)
+) engine=innodb comment = '瀛樺偍鐨勬偛瑙傞攣淇℃伅琛�';
+
+-- ----------------------------
+-- 11銆� Quartz闆嗙兢瀹炵幇鍚屾鏈哄埗鐨勮閿佽〃
+-- ---------------------------- 
+create table QRTZ_SIMPROP_TRIGGERS (
+    sched_name           varchar(120)    not null            comment '璋冨害鍚嶇О',
+    trigger_name         varchar(200)    not null            comment 'qrtz_triggers琛╰rigger_name鐨勫閿�',
+    trigger_group        varchar(200)    not null            comment 'qrtz_triggers琛╰rigger_group鐨勫閿�',
+    str_prop_1           varchar(512)    null                comment 'String绫诲瀷鐨則rigger鐨勭涓�涓弬鏁�',
+    str_prop_2           varchar(512)    null                comment 'String绫诲瀷鐨則rigger鐨勭浜屼釜鍙傛暟',
+    str_prop_3           varchar(512)    null                comment 'String绫诲瀷鐨則rigger鐨勭涓変釜鍙傛暟',
+    int_prop_1           int             null                comment 'int绫诲瀷鐨則rigger鐨勭涓�涓弬鏁�',
+    int_prop_2           int             null                comment 'int绫诲瀷鐨則rigger鐨勭浜屼釜鍙傛暟',
+    long_prop_1          bigint          null                comment 'long绫诲瀷鐨則rigger鐨勭涓�涓弬鏁�',
+    long_prop_2          bigint          null                comment 'long绫诲瀷鐨則rigger鐨勭浜屼釜鍙傛暟',
+    dec_prop_1           numeric(13,4)   null                comment 'decimal绫诲瀷鐨則rigger鐨勭涓�涓弬鏁�',
+    dec_prop_2           numeric(13,4)   null                comment 'decimal绫诲瀷鐨則rigger鐨勭浜屼釜鍙傛暟',
+    bool_prop_1          varchar(1)      null                comment 'Boolean绫诲瀷鐨則rigger鐨勭涓�涓弬鏁�',
+    bool_prop_2          varchar(1)      null                comment 'Boolean绫诲瀷鐨則rigger鐨勭浜屼釜鍙傛暟',
+    primary key (sched_name, trigger_name, trigger_group),
+    foreign key (sched_name, trigger_name, trigger_group) references QRTZ_TRIGGERS(sched_name, trigger_name, trigger_group)
+) engine=innodb comment = '鍚屾鏈哄埗鐨勮閿佽〃';
+
+commit;
\ No newline at end of file
diff --git a/sql/ry_20231130.sql b/sql/ry_20231130.sql
new file mode 100644
index 0000000..666aec4
--- /dev/null
+++ b/sql/ry_20231130.sql
@@ -0,0 +1,700 @@
+-- ----------------------------
+-- 1銆侀儴闂ㄨ〃
+-- ----------------------------
+drop table if exists sys_dept;
+create table sys_dept (
+  dept_id           bigint(20)      not null auto_increment    comment '閮ㄩ棬id',
+  parent_id         bigint(20)      default 0                  comment '鐖堕儴闂╥d',
+  ancestors         varchar(50)     default ''                 comment '绁栫骇鍒楄〃',
+  dept_name         varchar(30)     default ''                 comment '閮ㄩ棬鍚嶇О',
+  order_num         int(4)          default 0                  comment '鏄剧ず椤哄簭',
+  leader            varchar(20)     default null               comment '璐熻矗浜�',
+  phone             varchar(11)     default null               comment '鑱旂郴鐢佃瘽',
+  email             varchar(50)     default null               comment '閭',
+  status            char(1)         default '0'                comment '閮ㄩ棬鐘舵�侊紙0姝e父 1鍋滅敤锛�',
+  del_flag          char(1)         default '0'                comment '鍒犻櫎鏍囧織锛�0浠h〃瀛樺湪 2浠h〃鍒犻櫎锛�',
+  create_by         varchar(64)     default ''                 comment '鍒涘缓鑰�',
+  create_time 	    datetime                                   comment '鍒涘缓鏃堕棿',
+  update_by         varchar(64)     default ''                 comment '鏇存柊鑰�',
+  update_time       datetime                                   comment '鏇存柊鏃堕棿',
+  primary key (dept_id)
+) engine=innodb auto_increment=200 comment = '閮ㄩ棬琛�';
+
+-- ----------------------------
+-- 鍒濆鍖�-閮ㄩ棬琛ㄦ暟鎹�
+-- ----------------------------
+insert into sys_dept values(100,  0,   '0',          '姹熷',   0, '姹熷', '15888888888', 'ry@qq.com', '0', '0', 'admin', getdate(), '', null);
+insert into sys_dept values(101,  100, '0,100',      '娣卞湷鎬诲叕鍙�', 1, '姹熷', '15888888888', 'ry@qq.com', '0', '0', 'admin', getdate(), '', null);
+insert into sys_dept values(102,  100, '0,100',      '闀挎矙鍒嗗叕鍙�', 2, '姹熷', '15888888888', 'ry@qq.com', '0', '0', 'admin', getdate(), '', null);
+insert into sys_dept values(103,  101, '0,100,101',  '鐮斿彂閮ㄩ棬',   1, '姹熷', '15888888888', 'ry@qq.com', '0', '0', 'admin', getdate(), '', null);
+insert into sys_dept values(104,  101, '0,100,101',  '甯傚満閮ㄩ棬',   2, '姹熷', '15888888888', 'ry@qq.com', '0', '0', 'admin', getdate(), '', null);
+insert into sys_dept values(105,  101, '0,100,101',  '娴嬭瘯閮ㄩ棬',   3, '姹熷', '15888888888', 'ry@qq.com', '0', '0', 'admin', getdate(), '', null);
+insert into sys_dept values(106,  101, '0,100,101',  '璐㈠姟閮ㄩ棬',   4, '姹熷', '15888888888', 'ry@qq.com', '0', '0', 'admin', getdate(), '', null);
+insert into sys_dept values(107,  101, '0,100,101',  '杩愮淮閮ㄩ棬',   5, '姹熷', '15888888888', 'ry@qq.com', '0', '0', 'admin', getdate(), '', null);
+insert into sys_dept values(108,  102, '0,100,102',  '甯傚満閮ㄩ棬',   1, '姹熷', '15888888888', 'ry@qq.com', '0', '0', 'admin', getdate(), '', null);
+insert into sys_dept values(109,  102, '0,100,102',  '璐㈠姟閮ㄩ棬',   2, '姹熷', '15888888888', 'ry@qq.com', '0', '0', 'admin', getdate(), '', null);
+
+
+-- ----------------------------
+-- 2銆佺敤鎴蜂俊鎭〃
+-- ----------------------------
+drop table if exists sys_user;
+create table sys_user (
+  user_id           bigint(20)      not null auto_increment    comment '鐢ㄦ埛ID',
+  dept_id           bigint(20)      default null               comment '閮ㄩ棬ID',
+  user_name         varchar(30)     not null                   comment '鐢ㄦ埛璐﹀彿',
+  nick_name         varchar(30)     not null                   comment '鐢ㄦ埛鏄电О',
+  user_type         varchar(2)      default '00'               comment '鐢ㄦ埛绫诲瀷锛�00绯荤粺鐢ㄦ埛锛�',
+  email             varchar(50)     default ''                 comment '鐢ㄦ埛閭',
+  phonenumber       varchar(11)     default ''                 comment '鎵嬫満鍙风爜',
+  sex               char(1)         default '0'                comment '鐢ㄦ埛鎬у埆锛�0鐢� 1濂� 2鏈煡锛�',
+  avatar            varchar(100)    default ''                 comment '澶村儚鍦板潃',
+  password          varchar(100)    default ''                 comment '瀵嗙爜',
+  status            char(1)         default '0'                comment '甯愬彿鐘舵�侊紙0姝e父 1鍋滅敤锛�',
+  del_flag          char(1)         default '0'                comment '鍒犻櫎鏍囧織锛�0浠h〃瀛樺湪 2浠h〃鍒犻櫎锛�',
+  login_ip          varchar(128)    default ''                 comment '鏈�鍚庣櫥褰旾P',
+  login_date        datetime                                   comment '鏈�鍚庣櫥褰曟椂闂�',
+  create_by         varchar(64)     default ''                 comment '鍒涘缓鑰�',
+  create_time       datetime                                   comment '鍒涘缓鏃堕棿',
+  update_by         varchar(64)     default ''                 comment '鏇存柊鑰�',
+  update_time       datetime                                   comment '鏇存柊鏃堕棿',
+  remark            varchar(500)    default null               comment '澶囨敞',
+  primary key (user_id)
+) engine=innodb auto_increment=100 comment = '鐢ㄦ埛淇℃伅琛�';
+
+-- ----------------------------
+-- 鍒濆鍖�-鐢ㄦ埛淇℃伅琛ㄦ暟鎹�
+-- ----------------------------
+insert into sys_user values(1,  103, 'admin', '鑻ヤ緷', '00', 'ry@163.com', '15888888888', '1', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', getdate(), 'admin', sysdate(), '', null, '绠$悊鍛�');
+insert into sys_user values(2,  105, 'ry',    '鑻ヤ緷', '00', 'ry@qq.com',  '15666666666', '1', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', getdate(), 'admin', sysdate(), '', null, '娴嬭瘯鍛�');
+
+
+-- ----------------------------
+-- 3銆佸矖浣嶄俊鎭〃
+-- ----------------------------
+drop table if exists sys_post;
+create table sys_post
+(
+  post_id       bigint(20)      not null auto_increment    comment '宀椾綅ID',
+  post_code     varchar(64)     not null                   comment '宀椾綅缂栫爜',
+  post_name     varchar(50)     not null                   comment '宀椾綅鍚嶇О',
+  post_sort     int(4)          not null                   comment '鏄剧ず椤哄簭',
+  status        char(1)         not null                   comment '鐘舵�侊紙0姝e父 1鍋滅敤锛�',
+  create_by     varchar(64)     default ''                 comment '鍒涘缓鑰�',
+  create_time   datetime                                   comment '鍒涘缓鏃堕棿',
+  update_by     varchar(64)     default ''			       comment '鏇存柊鑰�',
+  update_time   datetime                                   comment '鏇存柊鏃堕棿',
+  remark        varchar(500)    default null               comment '澶囨敞',
+  primary key (post_id)
+) engine=innodb comment = '宀椾綅淇℃伅琛�';
+
+-- ----------------------------
+-- 鍒濆鍖�-宀椾綅淇℃伅琛ㄦ暟鎹�
+-- ----------------------------
+insert into sys_post values(1, 'ceo',  '钁d簨闀�',    1, '0', 'admin', sysdate(), '', null, '');
+insert into sys_post values(2, 'se',   '椤圭洰缁忕悊',  2, '0', 'admin', sysdate(), '', null, '');
+insert into sys_post values(3, 'hr',   '浜哄姏璧勬簮',  3, '0', 'admin', sysdate(), '', null, '');
+insert into sys_post values(4, 'user', '鏅�氬憳宸�',  4, '0', 'admin', sysdate(), '', null, '');
+
+
+-- ----------------------------
+-- 4銆佽鑹蹭俊鎭〃
+-- ----------------------------
+drop table if exists sys_role;
+create table sys_role (
+  role_id              bigint(20)      not null auto_increment    comment '瑙掕壊ID',
+  role_name            varchar(30)     not null                   comment '瑙掕壊鍚嶇О',
+  role_key             varchar(100)    not null                   comment '瑙掕壊鏉冮檺瀛楃涓�',
+  role_sort            int(4)          not null                   comment '鏄剧ず椤哄簭',
+  data_scope           char(1)         default '1'                comment '鏁版嵁鑼冨洿锛�1锛氬叏閮ㄦ暟鎹潈闄� 2锛氳嚜瀹氭暟鎹潈闄� 3锛氭湰閮ㄩ棬鏁版嵁鏉冮檺 4锛氭湰閮ㄩ棬鍙婁互涓嬫暟鎹潈闄愶級',
+  menu_check_strictly  tinyint(1)      default 1                  comment '鑿滃崟鏍戦�夋嫨椤规槸鍚﹀叧鑱旀樉绀�',
+  dept_check_strictly  tinyint(1)      default 1                  comment '閮ㄩ棬鏍戦�夋嫨椤规槸鍚﹀叧鑱旀樉绀�',
+  status               char(1)         not null                   comment '瑙掕壊鐘舵�侊紙0姝e父 1鍋滅敤锛�',
+  del_flag             char(1)         default '0'                comment '鍒犻櫎鏍囧織锛�0浠h〃瀛樺湪 2浠h〃鍒犻櫎锛�',
+  create_by            varchar(64)     default ''                 comment '鍒涘缓鑰�',
+  create_time          datetime                                   comment '鍒涘缓鏃堕棿',
+  update_by            varchar(64)     default ''                 comment '鏇存柊鑰�',
+  update_time          datetime                                   comment '鏇存柊鏃堕棿',
+  remark               varchar(500)    default null               comment '澶囨敞',
+  primary key (role_id)
+) engine=innodb auto_increment=100 comment = '瑙掕壊淇℃伅琛�';
+
+-- ----------------------------
+-- 鍒濆鍖�-瑙掕壊淇℃伅琛ㄦ暟鎹�
+-- ----------------------------
+insert into sys_role values('1', '瓒呯骇绠$悊鍛�',  'admin',  1, 1, 1, 1, '0', '0', 'admin', sysdate(), '', null, '瓒呯骇绠$悊鍛�');
+insert into sys_role values('2', '鏅�氳鑹�',    'common', 2, 2, 1, 1, '0', '0', 'admin', sysdate(), '', null, '鏅�氳鑹�');
+
+
+-- ----------------------------
+-- 5銆佽彍鍗曟潈闄愯〃
+-- ----------------------------
+drop table if exists sys_menu;
+create table sys_menu (
+  menu_id           bigint(20)      not null auto_increment    comment '鑿滃崟ID',
+  menu_name         varchar(50)     not null                   comment '鑿滃崟鍚嶇О',
+  parent_id         bigint(20)      default 0                  comment '鐖惰彍鍗旾D',
+  order_num         int(4)          default 0                  comment '鏄剧ず椤哄簭',
+  path              varchar(200)    default ''                 comment '璺敱鍦板潃',
+  component         varchar(255)    default null               comment '缁勪欢璺緞',
+  query             varchar(255)    default null               comment '璺敱鍙傛暟',
+  is_frame          int(1)          default 1                  comment '鏄惁涓哄閾撅紙0鏄� 1鍚︼級',
+  is_cache          int(1)          default 0                  comment '鏄惁缂撳瓨锛�0缂撳瓨 1涓嶇紦瀛橈級',
+  menu_type         char(1)         default ''                 comment '鑿滃崟绫诲瀷锛圡鐩綍 C鑿滃崟 F鎸夐挳锛�',
+  visible           char(1)         default 0                  comment '鑿滃崟鐘舵�侊紙0鏄剧ず 1闅愯棌锛�',
+  status            char(1)         default 0                  comment '鑿滃崟鐘舵�侊紙0姝e父 1鍋滅敤锛�',
+  perms             varchar(100)    default null               comment '鏉冮檺鏍囪瘑',
+  icon              varchar(100)    default '#'                comment '鑿滃崟鍥炬爣',
+  create_by         varchar(64)     default ''                 comment '鍒涘缓鑰�',
+  create_time       datetime                                   comment '鍒涘缓鏃堕棿',
+  update_by         varchar(64)     default ''                 comment '鏇存柊鑰�',
+  update_time       datetime                                   comment '鏇存柊鏃堕棿',
+  remark            varchar(500)    default ''                 comment '澶囨敞',
+  primary key (menu_id)
+) engine=innodb auto_increment=2000 comment = '鑿滃崟鏉冮檺琛�';
+
+-- ----------------------------
+-- 鍒濆鍖�-鑿滃崟淇℃伅琛ㄦ暟鎹�
+-- ----------------------------
+-- 涓�绾ц彍鍗�
+insert into sys_menu values('1', '绯荤粺绠$悊', '0', '1', 'system',           null, '', 1, 0, 'M', '0', '0', '', 'system',   'admin', sysdate(), '', null, '绯荤粺绠$悊鐩綍');
+insert into sys_menu values('2', '绯荤粺鐩戞帶', '0', '2', 'monitor',          null, '', 1, 0, 'M', '0', '0', '', 'monitor',  'admin', sysdate(), '', null, '绯荤粺鐩戞帶鐩綍');
+insert into sys_menu values('3', '绯荤粺宸ュ叿', '0', '3', 'tool',             null, '', 1, 0, 'M', '0', '0', '', 'tool',     'admin', sysdate(), '', null, '绯荤粺宸ュ叿鐩綍');
+insert into sys_menu values('4', '姹熻景瀹樼綉', '0', '4', 'http://jcdm.vip', null, '', 0, 0, 'M', '0', '0', '', 'guide',    'admin', sysdate(), '', null, '鑻ヤ緷瀹樼綉鍦板潃');
+-- 浜岀骇鑿滃崟
+insert into sys_menu values('100',  '鐢ㄦ埛绠$悊', '1',   '1', 'user',       'system/user/index',        '', 1, 0, 'C', '0', '0', 'system:user:list',        'user',          'admin', sysdate(), '', null, '鐢ㄦ埛绠$悊鑿滃崟');
+insert into sys_menu values('101',  '瑙掕壊绠$悊', '1',   '2', 'role',       'system/role/index',        '', 1, 0, 'C', '0', '0', 'system:role:list',        'peoples',       'admin', sysdate(), '', null, '瑙掕壊绠$悊鑿滃崟');
+insert into sys_menu values('102',  '鑿滃崟绠$悊', '1',   '3', 'menu',       'system/menu/index',        '', 1, 0, 'C', '0', '0', 'system:menu:list',        'tree-table',    'admin', sysdate(), '', null, '鑿滃崟绠$悊鑿滃崟');
+insert into sys_menu values('103',  '閮ㄩ棬绠$悊', '1',   '4', 'dept',       'system/dept/index',        '', 1, 0, 'C', '0', '0', 'system:dept:list',        'tree',          'admin', sysdate(), '', null, '閮ㄩ棬绠$悊鑿滃崟');
+insert into sys_menu values('104',  '宀椾綅绠$悊', '1',   '5', 'post',       'system/post/index',        '', 1, 0, 'C', '0', '0', 'system:post:list',        'post',          'admin', sysdate(), '', null, '宀椾綅绠$悊鑿滃崟');
+insert into sys_menu values('105',  '瀛楀吀绠$悊', '1',   '6', 'dict',       'system/dict/index',        '', 1, 0, 'C', '0', '0', 'system:dict:list',        'dict',          'admin', sysdate(), '', null, '瀛楀吀绠$悊鑿滃崟');
+insert into sys_menu values('106',  '鍙傛暟璁剧疆', '1',   '7', 'config',     'system/config/index',      '', 1, 0, 'C', '0', '0', 'system:config:list',      'edit',          'admin', sysdate(), '', null, '鍙傛暟璁剧疆鑿滃崟');
+insert into sys_menu values('107',  '閫氱煡鍏憡', '1',   '8', 'notice',     'system/notice/index',      '', 1, 0, 'C', '0', '0', 'system:notice:list',      'message',       'admin', sysdate(), '', null, '閫氱煡鍏憡鑿滃崟');
+insert into sys_menu values('108',  '鏃ュ織绠$悊', '1',   '9', 'log',        '',                         '', 1, 0, 'M', '0', '0', '',                        'log',           'admin', sysdate(), '', null, '鏃ュ織绠$悊鑿滃崟');
+insert into sys_menu values('109',  '鍦ㄧ嚎鐢ㄦ埛', '2',   '1', 'online',     'monitor/online/index',     '', 1, 0, 'C', '0', '0', 'monitor:online:list',     'online',        'admin', sysdate(), '', null, '鍦ㄧ嚎鐢ㄦ埛鑿滃崟');
+insert into sys_menu values('110',  '瀹氭椂浠诲姟', '2',   '2', 'job',        'monitor/job/index',        '', 1, 0, 'C', '0', '0', 'monitor:job:list',        'job',           'admin', sysdate(), '', null, '瀹氭椂浠诲姟鑿滃崟');
+insert into sys_menu values('111',  '鏁版嵁鐩戞帶', '2',   '3', 'druid',      'monitor/druid/index',      '', 1, 0, 'C', '0', '0', 'monitor:druid:list',      'druid',         'admin', sysdate(), '', null, '鏁版嵁鐩戞帶鑿滃崟');
+insert into sys_menu values('112',  '鏈嶅姟鐩戞帶', '2',   '4', 'server',     'monitor/server/index',     '', 1, 0, 'C', '0', '0', 'monitor:server:list',     'server',        'admin', sysdate(), '', null, '鏈嶅姟鐩戞帶鑿滃崟');
+insert into sys_menu values('113',  '缂撳瓨鐩戞帶', '2',   '5', 'cache',      'monitor/cache/index',      '', 1, 0, 'C', '0', '0', 'monitor:cache:list',      'redis',         'admin', sysdate(), '', null, '缂撳瓨鐩戞帶鑿滃崟');
+insert into sys_menu values('114',  '缂撳瓨鍒楄〃', '2',   '6', 'cacheList',  'monitor/cache/list',       '', 1, 0, 'C', '0', '0', 'monitor:cache:list',      'redis-list',    'admin', sysdate(), '', null, '缂撳瓨鍒楄〃鑿滃崟');
+insert into sys_menu values('115',  '琛ㄥ崟鏋勫缓', '3',   '1', 'build',      'tool/build/index',         '', 1, 0, 'C', '0', '0', 'tool:build:list',         'build',         'admin', sysdate(), '', null, '琛ㄥ崟鏋勫缓鑿滃崟');
+insert into sys_menu values('116',  '浠g爜鐢熸垚', '3',   '2', 'gen',        'tool/gen/index',           '', 1, 0, 'C', '0', '0', 'tool:gen:list',           'code',          'admin', sysdate(), '', null, '浠g爜鐢熸垚鑿滃崟');
+insert into sys_menu values('117',  '绯荤粺鎺ュ彛', '3',   '3', 'swagger',    'tool/swagger/index',       '', 1, 0, 'C', '0', '0', 'tool:swagger:list',       'swagger',       'admin', sysdate(), '', null, '绯荤粺鎺ュ彛鑿滃崟');
+-- 涓夌骇鑿滃崟
+insert into sys_menu values('500',  '鎿嶄綔鏃ュ織', '108', '1', 'operlog',    'monitor/operlog/index',    '', 1, 0, 'C', '0', '0', 'monitor:operlog:list',    'form',          'admin', sysdate(), '', null, '鎿嶄綔鏃ュ織鑿滃崟');
+insert into sys_menu values('501',  '鐧诲綍鏃ュ織', '108', '2', 'logininfor', 'monitor/logininfor/index', '', 1, 0, 'C', '0', '0', 'monitor:logininfor:list', 'logininfor',    'admin', sysdate(), '', null, '鐧诲綍鏃ュ織鑿滃崟');
+-- 鐢ㄦ埛绠$悊鎸夐挳
+insert into sys_menu values('1000', '鐢ㄦ埛鏌ヨ', '100', '1',  '', '', '', 1, 0, 'F', '0', '0', 'system:user:query',          '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1001', '鐢ㄦ埛鏂板', '100', '2',  '', '', '', 1, 0, 'F', '0', '0', 'system:user:add',            '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1002', '鐢ㄦ埛淇敼', '100', '3',  '', '', '', 1, 0, 'F', '0', '0', 'system:user:edit',           '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1003', '鐢ㄦ埛鍒犻櫎', '100', '4',  '', '', '', 1, 0, 'F', '0', '0', 'system:user:remove',         '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1004', '鐢ㄦ埛瀵煎嚭', '100', '5',  '', '', '', 1, 0, 'F', '0', '0', 'system:user:export',         '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1005', '鐢ㄦ埛瀵煎叆', '100', '6',  '', '', '', 1, 0, 'F', '0', '0', 'system:user:import',         '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1006', '閲嶇疆瀵嗙爜', '100', '7',  '', '', '', 1, 0, 'F', '0', '0', 'system:user:resetPwd',       '#', 'admin', sysdate(), '', null, '');
+-- 瑙掕壊绠$悊鎸夐挳
+insert into sys_menu values('1007', '瑙掕壊鏌ヨ', '101', '1',  '', '', '', 1, 0, 'F', '0', '0', 'system:role:query',          '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1008', '瑙掕壊鏂板', '101', '2',  '', '', '', 1, 0, 'F', '0', '0', 'system:role:add',            '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1009', '瑙掕壊淇敼', '101', '3',  '', '', '', 1, 0, 'F', '0', '0', 'system:role:edit',           '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1010', '瑙掕壊鍒犻櫎', '101', '4',  '', '', '', 1, 0, 'F', '0', '0', 'system:role:remove',         '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1011', '瑙掕壊瀵煎嚭', '101', '5',  '', '', '', 1, 0, 'F', '0', '0', 'system:role:export',         '#', 'admin', sysdate(), '', null, '');
+-- 鑿滃崟绠$悊鎸夐挳
+insert into sys_menu values('1012', '鑿滃崟鏌ヨ', '102', '1',  '', '', '', 1, 0, 'F', '0', '0', 'system:menu:query',          '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1013', '鑿滃崟鏂板', '102', '2',  '', '', '', 1, 0, 'F', '0', '0', 'system:menu:add',            '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1014', '鑿滃崟淇敼', '102', '3',  '', '', '', 1, 0, 'F', '0', '0', 'system:menu:edit',           '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1015', '鑿滃崟鍒犻櫎', '102', '4',  '', '', '', 1, 0, 'F', '0', '0', 'system:menu:remove',         '#', 'admin', sysdate(), '', null, '');
+-- 閮ㄩ棬绠$悊鎸夐挳
+insert into sys_menu values('1016', '閮ㄩ棬鏌ヨ', '103', '1',  '', '', '', 1, 0, 'F', '0', '0', 'system:dept:query',          '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1017', '閮ㄩ棬鏂板', '103', '2',  '', '', '', 1, 0, 'F', '0', '0', 'system:dept:add',            '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1018', '閮ㄩ棬淇敼', '103', '3',  '', '', '', 1, 0, 'F', '0', '0', 'system:dept:edit',           '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1019', '閮ㄩ棬鍒犻櫎', '103', '4',  '', '', '', 1, 0, 'F', '0', '0', 'system:dept:remove',         '#', 'admin', sysdate(), '', null, '');
+-- 宀椾綅绠$悊鎸夐挳
+insert into sys_menu values('1020', '宀椾綅鏌ヨ', '104', '1',  '', '', '', 1, 0, 'F', '0', '0', 'system:post:query',          '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1021', '宀椾綅鏂板', '104', '2',  '', '', '', 1, 0, 'F', '0', '0', 'system:post:add',            '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1022', '宀椾綅淇敼', '104', '3',  '', '', '', 1, 0, 'F', '0', '0', 'system:post:edit',           '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1023', '宀椾綅鍒犻櫎', '104', '4',  '', '', '', 1, 0, 'F', '0', '0', 'system:post:remove',         '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1024', '宀椾綅瀵煎嚭', '104', '5',  '', '', '', 1, 0, 'F', '0', '0', 'system:post:export',         '#', 'admin', sysdate(), '', null, '');
+-- 瀛楀吀绠$悊鎸夐挳
+insert into sys_menu values('1025', '瀛楀吀鏌ヨ', '105', '1', '#', '', '', 1, 0, 'F', '0', '0', 'system:dict:query',          '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1026', '瀛楀吀鏂板', '105', '2', '#', '', '', 1, 0, 'F', '0', '0', 'system:dict:add',            '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1027', '瀛楀吀淇敼', '105', '3', '#', '', '', 1, 0, 'F', '0', '0', 'system:dict:edit',           '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1028', '瀛楀吀鍒犻櫎', '105', '4', '#', '', '', 1, 0, 'F', '0', '0', 'system:dict:remove',         '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1029', '瀛楀吀瀵煎嚭', '105', '5', '#', '', '', 1, 0, 'F', '0', '0', 'system:dict:export',         '#', 'admin', sysdate(), '', null, '');
+-- 鍙傛暟璁剧疆鎸夐挳
+insert into sys_menu values('1030', '鍙傛暟鏌ヨ', '106', '1', '#', '', '', 1, 0, 'F', '0', '0', 'system:config:query',        '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1031', '鍙傛暟鏂板', '106', '2', '#', '', '', 1, 0, 'F', '0', '0', 'system:config:add',          '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1032', '鍙傛暟淇敼', '106', '3', '#', '', '', 1, 0, 'F', '0', '0', 'system:config:edit',         '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1033', '鍙傛暟鍒犻櫎', '106', '4', '#', '', '', 1, 0, 'F', '0', '0', 'system:config:remove',       '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1034', '鍙傛暟瀵煎嚭', '106', '5', '#', '', '', 1, 0, 'F', '0', '0', 'system:config:export',       '#', 'admin', sysdate(), '', null, '');
+-- 閫氱煡鍏憡鎸夐挳
+insert into sys_menu values('1035', '鍏憡鏌ヨ', '107', '1', '#', '', '', 1, 0, 'F', '0', '0', 'system:notice:query',        '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1036', '鍏憡鏂板', '107', '2', '#', '', '', 1, 0, 'F', '0', '0', 'system:notice:add',          '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1037', '鍏憡淇敼', '107', '3', '#', '', '', 1, 0, 'F', '0', '0', 'system:notice:edit',         '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1038', '鍏憡鍒犻櫎', '107', '4', '#', '', '', 1, 0, 'F', '0', '0', 'system:notice:remove',       '#', 'admin', sysdate(), '', null, '');
+-- 鎿嶄綔鏃ュ織鎸夐挳
+insert into sys_menu values('1039', '鎿嶄綔鏌ヨ', '500', '1', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:operlog:query',      '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1040', '鎿嶄綔鍒犻櫎', '500', '2', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:operlog:remove',     '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1041', '鏃ュ織瀵煎嚭', '500', '3', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:operlog:export',     '#', 'admin', sysdate(), '', null, '');
+-- 鐧诲綍鏃ュ織鎸夐挳
+insert into sys_menu values('1042', '鐧诲綍鏌ヨ', '501', '1', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:logininfor:query',   '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1043', '鐧诲綍鍒犻櫎', '501', '2', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:logininfor:remove',  '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1044', '鏃ュ織瀵煎嚭', '501', '3', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:logininfor:export',  '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1045', '璐︽埛瑙i攣', '501', '4', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:logininfor:unlock',  '#', 'admin', sysdate(), '', null, '');
+-- 鍦ㄧ嚎鐢ㄦ埛鎸夐挳
+insert into sys_menu values('1046', '鍦ㄧ嚎鏌ヨ', '109', '1', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:online:query',       '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1047', '鎵归噺寮洪��', '109', '2', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:online:batchLogout', '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1048', '鍗曟潯寮洪��', '109', '3', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:online:forceLogout', '#', 'admin', sysdate(), '', null, '');
+-- 瀹氭椂浠诲姟鎸夐挳
+insert into sys_menu values('1049', '浠诲姟鏌ヨ', '110', '1', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:job:query',          '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1050', '浠诲姟鏂板', '110', '2', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:job:add',            '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1051', '浠诲姟淇敼', '110', '3', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:job:edit',           '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1052', '浠诲姟鍒犻櫎', '110', '4', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:job:remove',         '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1053', '鐘舵�佷慨鏀�', '110', '5', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:job:changeStatus',   '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1054', '浠诲姟瀵煎嚭', '110', '6', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:job:export',         '#', 'admin', sysdate(), '', null, '');
+-- 浠g爜鐢熸垚鎸夐挳
+insert into sys_menu values('1055', '鐢熸垚鏌ヨ', '116', '1', '#', '', '', 1, 0, 'F', '0', '0', 'tool:gen:query',             '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1056', '鐢熸垚淇敼', '116', '2', '#', '', '', 1, 0, 'F', '0', '0', 'tool:gen:edit',              '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1057', '鐢熸垚鍒犻櫎', '116', '3', '#', '', '', 1, 0, 'F', '0', '0', 'tool:gen:remove',            '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1058', '瀵煎叆浠g爜', '116', '4', '#', '', '', 1, 0, 'F', '0', '0', 'tool:gen:import',            '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1059', '棰勮浠g爜', '116', '5', '#', '', '', 1, 0, 'F', '0', '0', 'tool:gen:preview',           '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1060', '鐢熸垚浠g爜', '116', '6', '#', '', '', 1, 0, 'F', '0', '0', 'tool:gen:code',              '#', 'admin', sysdate(), '', null, '');
+
+
+-- ----------------------------
+-- 6銆佺敤鎴峰拰瑙掕壊鍏宠仈琛�  鐢ㄦ埛N-1瑙掕壊
+-- ----------------------------
+drop table if exists sys_user_role;
+create table sys_user_role (
+  user_id   bigint(20) not null comment '鐢ㄦ埛ID',
+  role_id   bigint(20) not null comment '瑙掕壊ID',
+  primary key(user_id, role_id)
+) engine=innodb comment = '鐢ㄦ埛鍜岃鑹插叧鑱旇〃';
+
+-- ----------------------------
+-- 鍒濆鍖�-鐢ㄦ埛鍜岃鑹插叧鑱旇〃鏁版嵁
+-- ----------------------------
+insert into sys_user_role values ('1', '1');
+insert into sys_user_role values ('2', '2');
+
+
+-- ----------------------------
+-- 7銆佽鑹插拰鑿滃崟鍏宠仈琛�  瑙掕壊1-N鑿滃崟
+-- ----------------------------
+drop table if exists sys_role_menu;
+create table sys_role_menu (
+  role_id   bigint(20) not null comment '瑙掕壊ID',
+  menu_id   bigint(20) not null comment '鑿滃崟ID',
+  primary key(role_id, menu_id)
+) engine=innodb comment = '瑙掕壊鍜岃彍鍗曞叧鑱旇〃';
+
+-- ----------------------------
+-- 鍒濆鍖�-瑙掕壊鍜岃彍鍗曞叧鑱旇〃鏁版嵁
+-- ----------------------------
+insert into sys_role_menu values ('2', '1');
+insert into sys_role_menu values ('2', '2');
+insert into sys_role_menu values ('2', '3');
+insert into sys_role_menu values ('2', '4');
+insert into sys_role_menu values ('2', '100');
+insert into sys_role_menu values ('2', '101');
+insert into sys_role_menu values ('2', '102');
+insert into sys_role_menu values ('2', '103');
+insert into sys_role_menu values ('2', '104');
+insert into sys_role_menu values ('2', '105');
+insert into sys_role_menu values ('2', '106');
+insert into sys_role_menu values ('2', '107');
+insert into sys_role_menu values ('2', '108');
+insert into sys_role_menu values ('2', '109');
+insert into sys_role_menu values ('2', '110');
+insert into sys_role_menu values ('2', '111');
+insert into sys_role_menu values ('2', '112');
+insert into sys_role_menu values ('2', '113');
+insert into sys_role_menu values ('2', '114');
+insert into sys_role_menu values ('2', '115');
+insert into sys_role_menu values ('2', '116');
+insert into sys_role_menu values ('2', '117');
+insert into sys_role_menu values ('2', '500');
+insert into sys_role_menu values ('2', '501');
+insert into sys_role_menu values ('2', '1000');
+insert into sys_role_menu values ('2', '1001');
+insert into sys_role_menu values ('2', '1002');
+insert into sys_role_menu values ('2', '1003');
+insert into sys_role_menu values ('2', '1004');
+insert into sys_role_menu values ('2', '1005');
+insert into sys_role_menu values ('2', '1006');
+insert into sys_role_menu values ('2', '1007');
+insert into sys_role_menu values ('2', '1008');
+insert into sys_role_menu values ('2', '1009');
+insert into sys_role_menu values ('2', '1010');
+insert into sys_role_menu values ('2', '1011');
+insert into sys_role_menu values ('2', '1012');
+insert into sys_role_menu values ('2', '1013');
+insert into sys_role_menu values ('2', '1014');
+insert into sys_role_menu values ('2', '1015');
+insert into sys_role_menu values ('2', '1016');
+insert into sys_role_menu values ('2', '1017');
+insert into sys_role_menu values ('2', '1018');
+insert into sys_role_menu values ('2', '1019');
+insert into sys_role_menu values ('2', '1020');
+insert into sys_role_menu values ('2', '1021');
+insert into sys_role_menu values ('2', '1022');
+insert into sys_role_menu values ('2', '1023');
+insert into sys_role_menu values ('2', '1024');
+insert into sys_role_menu values ('2', '1025');
+insert into sys_role_menu values ('2', '1026');
+insert into sys_role_menu values ('2', '1027');
+insert into sys_role_menu values ('2', '1028');
+insert into sys_role_menu values ('2', '1029');
+insert into sys_role_menu values ('2', '1030');
+insert into sys_role_menu values ('2', '1031');
+insert into sys_role_menu values ('2', '1032');
+insert into sys_role_menu values ('2', '1033');
+insert into sys_role_menu values ('2', '1034');
+insert into sys_role_menu values ('2', '1035');
+insert into sys_role_menu values ('2', '1036');
+insert into sys_role_menu values ('2', '1037');
+insert into sys_role_menu values ('2', '1038');
+insert into sys_role_menu values ('2', '1039');
+insert into sys_role_menu values ('2', '1040');
+insert into sys_role_menu values ('2', '1041');
+insert into sys_role_menu values ('2', '1042');
+insert into sys_role_menu values ('2', '1043');
+insert into sys_role_menu values ('2', '1044');
+insert into sys_role_menu values ('2', '1045');
+insert into sys_role_menu values ('2', '1046');
+insert into sys_role_menu values ('2', '1047');
+insert into sys_role_menu values ('2', '1048');
+insert into sys_role_menu values ('2', '1049');
+insert into sys_role_menu values ('2', '1050');
+insert into sys_role_menu values ('2', '1051');
+insert into sys_role_menu values ('2', '1052');
+insert into sys_role_menu values ('2', '1053');
+insert into sys_role_menu values ('2', '1054');
+insert into sys_role_menu values ('2', '1055');
+insert into sys_role_menu values ('2', '1056');
+insert into sys_role_menu values ('2', '1057');
+insert into sys_role_menu values ('2', '1058');
+insert into sys_role_menu values ('2', '1059');
+insert into sys_role_menu values ('2', '1060');
+
+-- ----------------------------
+-- 8銆佽鑹插拰閮ㄩ棬鍏宠仈琛�  瑙掕壊1-N閮ㄩ棬
+-- ----------------------------
+drop table if exists sys_role_dept;
+create table sys_role_dept (
+  role_id   bigint(20) not null comment '瑙掕壊ID',
+  dept_id   bigint(20) not null comment '閮ㄩ棬ID',
+  primary key(role_id, dept_id)
+) engine=innodb comment = '瑙掕壊鍜岄儴闂ㄥ叧鑱旇〃';
+
+-- ----------------------------
+-- 鍒濆鍖�-瑙掕壊鍜岄儴闂ㄥ叧鑱旇〃鏁版嵁
+-- ----------------------------
+insert into sys_role_dept values ('2', '100');
+insert into sys_role_dept values ('2', '101');
+insert into sys_role_dept values ('2', '105');
+
+
+-- ----------------------------
+-- 9銆佺敤鎴蜂笌宀椾綅鍏宠仈琛�  鐢ㄦ埛1-N宀椾綅
+-- ----------------------------
+drop table if exists sys_user_post;
+create table sys_user_post
+(
+  user_id   bigint(20) not null comment '鐢ㄦ埛ID',
+  post_id   bigint(20) not null comment '宀椾綅ID',
+  primary key (user_id, post_id)
+) engine=innodb comment = '鐢ㄦ埛涓庡矖浣嶅叧鑱旇〃';
+
+-- ----------------------------
+-- 鍒濆鍖�-鐢ㄦ埛涓庡矖浣嶅叧鑱旇〃鏁版嵁
+-- ----------------------------
+insert into sys_user_post values ('1', '1');
+insert into sys_user_post values ('2', '2');
+
+
+-- ----------------------------
+-- 10銆佹搷浣滄棩蹇楄褰�
+-- ----------------------------
+drop table if exists sys_oper_log;
+create table sys_oper_log (
+  oper_id           bigint(20)      not null auto_increment    comment '鏃ュ織涓婚敭',
+  title             varchar(50)     default ''                 comment '妯″潡鏍囬',
+  business_type     int(2)          default 0                  comment '涓氬姟绫诲瀷锛�0鍏跺畠 1鏂板 2淇敼 3鍒犻櫎锛�',
+  method            varchar(100)    default ''                 comment '鏂规硶鍚嶇О',
+  request_method    varchar(10)     default ''                 comment '璇锋眰鏂瑰紡',
+  operator_type     int(1)          default 0                  comment '鎿嶄綔绫诲埆锛�0鍏跺畠 1鍚庡彴鐢ㄦ埛 2鎵嬫満绔敤鎴凤級',
+  oper_name         varchar(50)     default ''                 comment '鎿嶄綔浜哄憳',
+  dept_name         varchar(50)     default ''                 comment '閮ㄩ棬鍚嶇О',
+  oper_url          varchar(255)    default ''                 comment '璇锋眰URL',
+  oper_ip           varchar(128)    default ''                 comment '涓绘満鍦板潃',
+  oper_location     varchar(255)    default ''                 comment '鎿嶄綔鍦扮偣',
+  oper_param        varchar(2000)   default ''                 comment '璇锋眰鍙傛暟',
+  json_result       varchar(2000)   default ''                 comment '杩斿洖鍙傛暟',
+  status            int(1)          default 0                  comment '鎿嶄綔鐘舵�侊紙0姝e父 1寮傚父锛�',
+  error_msg         varchar(2000)   default ''                 comment '閿欒娑堟伅',
+  oper_time         datetime                                   comment '鎿嶄綔鏃堕棿',
+  cost_time         bigint(20)      default 0                  comment '娑堣�楁椂闂�',
+  primary key (oper_id),
+  key idx_sys_oper_log_bt (business_type),
+  key idx_sys_oper_log_s  (status),
+  key idx_sys_oper_log_ot (oper_time)
+) engine=innodb auto_increment=100 comment = '鎿嶄綔鏃ュ織璁板綍';
+
+
+-- ----------------------------
+-- 11銆佸瓧鍏哥被鍨嬭〃
+-- ----------------------------
+drop table if exists sys_dict_type;
+create table sys_dict_type
+(
+  dict_id          bigint(20)      not null auto_increment    comment '瀛楀吀涓婚敭',
+  dict_name        varchar(100)    default ''                 comment '瀛楀吀鍚嶇О',
+  dict_type        varchar(100)    default ''                 comment '瀛楀吀绫诲瀷',
+  status           char(1)         default '0'                comment '鐘舵�侊紙0姝e父 1鍋滅敤锛�',
+  create_by        varchar(64)     default ''                 comment '鍒涘缓鑰�',
+  create_time      datetime                                   comment '鍒涘缓鏃堕棿',
+  update_by        varchar(64)     default ''                 comment '鏇存柊鑰�',
+  update_time      datetime                                   comment '鏇存柊鏃堕棿',
+  remark           varchar(500)    default null               comment '澶囨敞',
+  primary key (dict_id),
+  unique (dict_type)
+) engine=innodb auto_increment=100 comment = '瀛楀吀绫诲瀷琛�';
+
+insert into sys_dict_type values(1,  '鐢ㄦ埛鎬у埆', 'sys_user_sex',        '0', 'admin', sysdate(), '', null, '鐢ㄦ埛鎬у埆鍒楄〃');
+insert into sys_dict_type values(2,  '鑿滃崟鐘舵��', 'sys_show_hide',       '0', 'admin', sysdate(), '', null, '鑿滃崟鐘舵�佸垪琛�');
+insert into sys_dict_type values(3,  '绯荤粺寮�鍏�', 'sys_normal_disable',  '0', 'admin', sysdate(), '', null, '绯荤粺寮�鍏冲垪琛�');
+insert into sys_dict_type values(4,  '浠诲姟鐘舵��', 'sys_job_status',      '0', 'admin', sysdate(), '', null, '浠诲姟鐘舵�佸垪琛�');
+insert into sys_dict_type values(5,  '浠诲姟鍒嗙粍', 'sys_job_group',       '0', 'admin', sysdate(), '', null, '浠诲姟鍒嗙粍鍒楄〃');
+insert into sys_dict_type values(6,  '绯荤粺鏄惁', 'sys_yes_no',          '0', 'admin', sysdate(), '', null, '绯荤粺鏄惁鍒楄〃');
+insert into sys_dict_type values(7,  '閫氱煡绫诲瀷', 'sys_notice_type',     '0', 'admin', sysdate(), '', null, '閫氱煡绫诲瀷鍒楄〃');
+insert into sys_dict_type values(8,  '閫氱煡鐘舵��', 'sys_notice_status',   '0', 'admin', sysdate(), '', null, '閫氱煡鐘舵�佸垪琛�');
+insert into sys_dict_type values(9,  '鎿嶄綔绫诲瀷', 'sys_oper_type',       '0', 'admin', sysdate(), '', null, '鎿嶄綔绫诲瀷鍒楄〃');
+insert into sys_dict_type values(10, '绯荤粺鐘舵��', 'sys_common_status',   '0', 'admin', sysdate(), '', null, '鐧诲綍鐘舵�佸垪琛�');
+
+
+-- ----------------------------
+-- 12銆佸瓧鍏告暟鎹〃
+-- ----------------------------
+drop table if exists sys_dict_data;
+create table sys_dict_data
+(
+  dict_code        bigint(20)      not null auto_increment    comment '瀛楀吀缂栫爜',
+  dict_sort        int(4)          default 0                  comment '瀛楀吀鎺掑簭',
+  dict_label       varchar(100)    default ''                 comment '瀛楀吀鏍囩',
+  dict_value       varchar(100)    default ''                 comment '瀛楀吀閿��',
+  dict_type        varchar(100)    default ''                 comment '瀛楀吀绫诲瀷',
+  css_class        varchar(100)    default null               comment '鏍峰紡灞炴�э紙鍏朵粬鏍峰紡鎵╁睍锛�',
+  list_class       varchar(100)    default null               comment '琛ㄦ牸鍥炴樉鏍峰紡',
+  is_default       char(1)         default 'N'                comment '鏄惁榛樿锛圷鏄� N鍚︼級',
+  status           char(1)         default '0'                comment '鐘舵�侊紙0姝e父 1鍋滅敤锛�',
+  create_by        varchar(64)     default ''                 comment '鍒涘缓鑰�',
+  create_time      datetime                                   comment '鍒涘缓鏃堕棿',
+  update_by        varchar(64)     default ''                 comment '鏇存柊鑰�',
+  update_time      datetime                                   comment '鏇存柊鏃堕棿',
+  remark           varchar(500)    default null               comment '澶囨敞',
+  primary key (dict_code)
+) engine=innodb auto_increment=100 comment = '瀛楀吀鏁版嵁琛�';
+
+insert into sys_dict_data values(1,  1,  '鐢�',       '0',       'sys_user_sex',        '',   '',        'Y', '0', 'admin', sysdate(), '', null, '鎬у埆鐢�');
+insert into sys_dict_data values(2,  2,  '濂�',       '1',       'sys_user_sex',        '',   '',        'N', '0', 'admin', sysdate(), '', null, '鎬у埆濂�');
+insert into sys_dict_data values(3,  3,  '鏈煡',     '2',       'sys_user_sex',        '',   '',        'N', '0', 'admin', sysdate(), '', null, '鎬у埆鏈煡');
+insert into sys_dict_data values(4,  1,  '鏄剧ず',     '0',       'sys_show_hide',       '',   'primary', 'Y', '0', 'admin', sysdate(), '', null, '鏄剧ず鑿滃崟');
+insert into sys_dict_data values(5,  2,  '闅愯棌',     '1',       'sys_show_hide',       '',   'danger',  'N', '0', 'admin', sysdate(), '', null, '闅愯棌鑿滃崟');
+insert into sys_dict_data values(6,  1,  '姝e父',     '0',       'sys_normal_disable',  '',   'primary', 'Y', '0', 'admin', sysdate(), '', null, '姝e父鐘舵��');
+insert into sys_dict_data values(7,  2,  '鍋滅敤',     '1',       'sys_normal_disable',  '',   'danger',  'N', '0', 'admin', sysdate(), '', null, '鍋滅敤鐘舵��');
+insert into sys_dict_data values(8,  1,  '姝e父',     '0',       'sys_job_status',      '',   'primary', 'Y', '0', 'admin', sysdate(), '', null, '姝e父鐘舵��');
+insert into sys_dict_data values(9,  2,  '鏆傚仠',     '1',       'sys_job_status',      '',   'danger',  'N', '0', 'admin', sysdate(), '', null, '鍋滅敤鐘舵��');
+insert into sys_dict_data values(10, 1,  '榛樿',     'DEFAULT', 'sys_job_group',       '',   '',        'Y', '0', 'admin', sysdate(), '', null, '榛樿鍒嗙粍');
+insert into sys_dict_data values(11, 2,  '绯荤粺',     'SYSTEM',  'sys_job_group',       '',   '',        'N', '0', 'admin', sysdate(), '', null, '绯荤粺鍒嗙粍');
+insert into sys_dict_data values(12, 1,  '鏄�',       'Y',       'sys_yes_no',          '',   'primary', 'Y', '0', 'admin', sysdate(), '', null, '绯荤粺榛樿鏄�');
+insert into sys_dict_data values(13, 2,  '鍚�',       'N',       'sys_yes_no',          '',   'danger',  'N', '0', 'admin', sysdate(), '', null, '绯荤粺榛樿鍚�');
+insert into sys_dict_data values(14, 1,  '閫氱煡',     '1',       'sys_notice_type',     '',   'warning', 'Y', '0', 'admin', sysdate(), '', null, '閫氱煡');
+insert into sys_dict_data values(15, 2,  '鍏憡',     '2',       'sys_notice_type',     '',   'success', 'N', '0', 'admin', sysdate(), '', null, '鍏憡');
+insert into sys_dict_data values(16, 1,  '姝e父',     '0',       'sys_notice_status',   '',   'primary', 'Y', '0', 'admin', sysdate(), '', null, '姝e父鐘舵��');
+insert into sys_dict_data values(17, 2,  '鍏抽棴',     '1',       'sys_notice_status',   '',   'danger',  'N', '0', 'admin', sysdate(), '', null, '鍏抽棴鐘舵��');
+insert into sys_dict_data values(18, 99, '鍏朵粬',     '0',       'sys_oper_type',       '',   'info',    'N', '0', 'admin', sysdate(), '', null, '鍏朵粬鎿嶄綔');
+insert into sys_dict_data values(19, 1,  '鏂板',     '1',       'sys_oper_type',       '',   'info',    'N', '0', 'admin', sysdate(), '', null, '鏂板鎿嶄綔');
+insert into sys_dict_data values(20, 2,  '淇敼',     '2',       'sys_oper_type',       '',   'info',    'N', '0', 'admin', sysdate(), '', null, '淇敼鎿嶄綔');
+insert into sys_dict_data values(21, 3,  '鍒犻櫎',     '3',       'sys_oper_type',       '',   'danger',  'N', '0', 'admin', sysdate(), '', null, '鍒犻櫎鎿嶄綔');
+insert into sys_dict_data values(22, 4,  '鎺堟潈',     '4',       'sys_oper_type',       '',   'primary', 'N', '0', 'admin', sysdate(), '', null, '鎺堟潈鎿嶄綔');
+insert into sys_dict_data values(23, 5,  '瀵煎嚭',     '5',       'sys_oper_type',       '',   'warning', 'N', '0', 'admin', sysdate(), '', null, '瀵煎嚭鎿嶄綔');
+insert into sys_dict_data values(24, 6,  '瀵煎叆',     '6',       'sys_oper_type',       '',   'warning', 'N', '0', 'admin', sysdate(), '', null, '瀵煎叆鎿嶄綔');
+insert into sys_dict_data values(25, 7,  '寮洪��',     '7',       'sys_oper_type',       '',   'danger',  'N', '0', 'admin', sysdate(), '', null, '寮洪��鎿嶄綔');
+insert into sys_dict_data values(26, 8,  '鐢熸垚浠g爜', '8',       'sys_oper_type',       '',   'warning', 'N', '0', 'admin', sysdate(), '', null, '鐢熸垚鎿嶄綔');
+insert into sys_dict_data values(27, 9,  '娓呯┖鏁版嵁', '9',       'sys_oper_type',       '',   'danger',  'N', '0', 'admin', sysdate(), '', null, '娓呯┖鎿嶄綔');
+insert into sys_dict_data values(28, 1,  '鎴愬姛',     '0',       'sys_common_status',   '',   'primary', 'N', '0', 'admin', sysdate(), '', null, '姝e父鐘舵��');
+insert into sys_dict_data values(29, 2,  '澶辫触',     '1',       'sys_common_status',   '',   'danger',  'N', '0', 'admin', sysdate(), '', null, '鍋滅敤鐘舵��');
+
+
+-- ----------------------------
+-- 13銆佸弬鏁伴厤缃〃
+-- ----------------------------
+drop table if exists sys_config;
+create table sys_config (
+  config_id         int(5)          not null auto_increment    comment '鍙傛暟涓婚敭',
+  config_name       varchar(100)    default ''                 comment '鍙傛暟鍚嶇О',
+  config_key        varchar(100)    default ''                 comment '鍙傛暟閿悕',
+  config_value      varchar(500)    default ''                 comment '鍙傛暟閿��',
+  config_type       char(1)         default 'N'                comment '绯荤粺鍐呯疆锛圷鏄� N鍚︼級',
+  create_by         varchar(64)     default ''                 comment '鍒涘缓鑰�',
+  create_time       datetime                                   comment '鍒涘缓鏃堕棿',
+  update_by         varchar(64)     default ''                 comment '鏇存柊鑰�',
+  update_time       datetime                                   comment '鏇存柊鏃堕棿',
+  remark            varchar(500)    default null               comment '澶囨敞',
+  primary key (config_id)
+) engine=innodb auto_increment=100 comment = '鍙傛暟閰嶇疆琛�';
+
+insert into sys_config values(1, '涓绘鏋堕〉-榛樿鐨偆鏍峰紡鍚嶇О',     'sys.index.skinName',            'skin-blue',     'Y', 'admin', sysdate(), '', null, '钃濊壊 skin-blue銆佺豢鑹� skin-green銆佺传鑹� skin-purple銆佺孩鑹� skin-red銆侀粍鑹� skin-yellow' );
+insert into sys_config values(2, '鐢ㄦ埛绠$悊-璐﹀彿鍒濆瀵嗙爜',         'sys.user.initPassword',         '123456',        'Y', 'admin', sysdate(), '', null, '鍒濆鍖栧瘑鐮� 123456' );
+insert into sys_config values(3, '涓绘鏋堕〉-渚ц竟鏍忎富棰�',           'sys.index.sideTheme',           'theme-dark',    'Y', 'admin', sysdate(), '', null, '娣辫壊涓婚theme-dark锛屾祬鑹蹭富棰榯heme-light' );
+insert into sys_config values(4, '璐﹀彿鑷姪-楠岃瘉鐮佸紑鍏�',           'sys.account.captchaEnabled',    'true',          'Y', 'admin', sysdate(), '', null, '鏄惁寮�鍚獙璇佺爜鍔熻兘锛坱rue寮�鍚紝false鍏抽棴锛�');
+insert into sys_config values(5, '璐﹀彿鑷姪-鏄惁寮�鍚敤鎴锋敞鍐屽姛鑳�', 'sys.account.registerUser',      'false',         'Y', 'admin', sysdate(), '', null, '鏄惁寮�鍚敞鍐岀敤鎴峰姛鑳斤紙true寮�鍚紝false鍏抽棴锛�');
+insert into sys_config values(6, '鐢ㄦ埛鐧诲綍-榛戝悕鍗曞垪琛�',           'sys.login.blackIPList',         '',              'Y', 'admin', sysdate(), '', null, '璁剧疆鐧诲綍IP榛戝悕鍗曢檺鍒讹紝澶氫釜鍖归厤椤逛互;鍒嗛殧锛屾敮鎸佸尮閰嶏紙*閫氶厤銆佺綉娈碉級');
+
+
+-- ----------------------------
+-- 14銆佺郴缁熻闂褰�
+-- ----------------------------
+drop table if exists sys_logininfor;
+create table sys_logininfor (
+  info_id        bigint(20)     not null auto_increment   comment '璁块棶ID',
+  user_name      varchar(50)    default ''                comment '鐢ㄦ埛璐﹀彿',
+  ipaddr         varchar(128)   default ''                comment '鐧诲綍IP鍦板潃',
+  login_location varchar(255)   default ''                comment '鐧诲綍鍦扮偣',
+  browser        varchar(50)    default ''                comment '娴忚鍣ㄧ被鍨�',
+  os             varchar(50)    default ''                comment '鎿嶄綔绯荤粺',
+  status         char(1)        default '0'               comment '鐧诲綍鐘舵�侊紙0鎴愬姛 1澶辫触锛�',
+  msg            varchar(255)   default ''                comment '鎻愮ず娑堟伅',
+  login_time     datetime                                 comment '璁块棶鏃堕棿',
+  primary key (info_id),
+  key idx_sys_logininfor_s  (status),
+  key idx_sys_logininfor_lt (login_time)
+) engine=innodb auto_increment=100 comment = '绯荤粺璁块棶璁板綍';
+
+
+-- ----------------------------
+-- 15銆佸畾鏃朵换鍔¤皟搴﹁〃
+-- ----------------------------
+drop table if exists sys_job;
+create table sys_job (
+  job_id              bigint(20)    not null auto_increment    comment '浠诲姟ID',
+  job_name            varchar(64)   default ''                 comment '浠诲姟鍚嶇О',
+  job_group           varchar(64)   default 'DEFAULT'          comment '浠诲姟缁勫悕',
+  invoke_target       varchar(500)  not null                   comment '璋冪敤鐩爣瀛楃涓�',
+  cron_expression     varchar(255)  default ''                 comment 'cron鎵ц琛ㄨ揪寮�',
+  misfire_policy      varchar(20)   default '3'                comment '璁″垝鎵ц閿欒绛栫暐锛�1绔嬪嵆鎵ц 2鎵ц涓�娆� 3鏀惧純鎵ц锛�',
+  concurrent          char(1)       default '1'                comment '鏄惁骞跺彂鎵ц锛�0鍏佽 1绂佹锛�',
+  status              char(1)       default '0'                comment '鐘舵�侊紙0姝e父 1鏆傚仠锛�',
+  create_by           varchar(64)   default ''                 comment '鍒涘缓鑰�',
+  create_time         datetime                                 comment '鍒涘缓鏃堕棿',
+  update_by           varchar(64)   default ''                 comment '鏇存柊鑰�',
+  update_time         datetime                                 comment '鏇存柊鏃堕棿',
+  remark              varchar(500)  default ''                 comment '澶囨敞淇℃伅',
+  primary key (job_id, job_name, job_group)
+) engine=innodb auto_increment=100 comment = '瀹氭椂浠诲姟璋冨害琛�';
+
+insert into sys_job values(1, '绯荤粺榛樿锛堟棤鍙傦級', 'DEFAULT', 'ryTask.ryNoParams',        '0/10 * * * * ?', '3', '1', '1', 'admin', sysdate(), '', null, '');
+insert into sys_job values(2, '绯荤粺榛樿锛堟湁鍙傦級', 'DEFAULT', 'ryTask.ryParams(\'ry\')',  '0/15 * * * * ?', '3', '1', '1', 'admin', sysdate(), '', null, '');
+insert into sys_job values(3, '绯荤粺榛樿锛堝鍙傦級', 'DEFAULT', 'ryTask.ryMultipleParams(\'ry\', true, 2000L, 316.50D, 100)',  '0/20 * * * * ?', '3', '1', '1', 'admin', sysdate(), '', null, '');
+
+
+-- ----------------------------
+-- 16銆佸畾鏃朵换鍔¤皟搴︽棩蹇楄〃
+-- ----------------------------
+drop table if exists sys_job_log;
+create table sys_job_log (
+  job_log_id          bigint(20)     not null auto_increment    comment '浠诲姟鏃ュ織ID',
+  job_name            varchar(64)    not null                   comment '浠诲姟鍚嶇О',
+  job_group           varchar(64)    not null                   comment '浠诲姟缁勫悕',
+  invoke_target       varchar(500)   not null                   comment '璋冪敤鐩爣瀛楃涓�',
+  job_message         varchar(500)                              comment '鏃ュ織淇℃伅',
+  status              char(1)        default '0'                comment '鎵ц鐘舵�侊紙0姝e父 1澶辫触锛�',
+  exception_info      varchar(2000)  default ''                 comment '寮傚父淇℃伅',
+  create_time         datetime                                  comment '鍒涘缓鏃堕棿',
+  primary key (job_log_id)
+) engine=innodb comment = '瀹氭椂浠诲姟璋冨害鏃ュ織琛�';
+
+
+-- ----------------------------
+-- 17銆侀�氱煡鍏憡琛�
+-- ----------------------------
+drop table if exists sys_notice;
+create table sys_notice (
+  notice_id         int(4)          not null auto_increment    comment '鍏憡ID',
+  notice_title      varchar(50)     not null                   comment '鍏憡鏍囬',
+  notice_type       char(1)         not null                   comment '鍏憡绫诲瀷锛�1閫氱煡 2鍏憡锛�',
+  notice_content    longblob        default null               comment '鍏憡鍐呭',
+  status            char(1)         default '0'                comment '鍏憡鐘舵�侊紙0姝e父 1鍏抽棴锛�',
+  create_by         varchar(64)     default ''                 comment '鍒涘缓鑰�',
+  create_time       datetime                                   comment '鍒涘缓鏃堕棿',
+  update_by         varchar(64)     default ''                 comment '鏇存柊鑰�',
+  update_time       datetime                                   comment '鏇存柊鏃堕棿',
+  remark            varchar(255)    default null               comment '澶囨敞',
+  primary key (notice_id)
+) engine=innodb auto_increment=10 comment = '閫氱煡鍏憡琛�';
+
+-- ----------------------------
+-- 鍒濆鍖�-鍏憡淇℃伅琛ㄦ暟鎹�
+-- ----------------------------
+insert into sys_notice values('1', '娓╅Θ鎻愰啋锛�2018-07-01 鑻ヤ緷鏂扮増鏈彂甯冨暒', '2', '鏂扮増鏈唴瀹�', '0', 'admin', sysdate(), '', null, '绠$悊鍛�');
+insert into sys_notice values('2', '缁存姢閫氱煡锛�2018-07-01 鑻ヤ緷绯荤粺鍑屾櫒缁存姢', '1', '缁存姢鍐呭',   '0', 'admin', sysdate(), '', null, '绠$悊鍛�');
+
+
+-- ----------------------------
+-- 18銆佷唬鐮佺敓鎴愪笟鍔¤〃
+-- ----------------------------
+drop table if exists gen_table;
+create table gen_table (
+  table_id          bigint(20)      not null auto_increment    comment '缂栧彿',
+  table_name        varchar(200)    default ''                 comment '琛ㄥ悕绉�',
+  table_comment     varchar(500)    default ''                 comment '琛ㄦ弿杩�',
+  sub_table_name    varchar(64)     default null               comment '鍏宠仈瀛愯〃鐨勮〃鍚�',
+  sub_table_fk_name varchar(64)     default null               comment '瀛愯〃鍏宠仈鐨勫閿悕',
+  class_name        varchar(100)    default ''                 comment '瀹炰綋绫诲悕绉�',
+  tpl_category      varchar(200)    default 'crud'             comment '浣跨敤鐨勬ā鏉匡紙crud鍗曡〃鎿嶄綔 tree鏍戣〃鎿嶄綔锛�',
+  tpl_web_type      varchar(30)     default ''                 comment '鍓嶇妯℃澘绫诲瀷锛坋lement-ui妯$増 element-plus妯$増锛�',
+  package_name      varchar(100)                               comment '鐢熸垚鍖呰矾寰�',
+  module_name       varchar(30)                                comment '鐢熸垚妯″潡鍚�',
+  business_name     varchar(30)                                comment '鐢熸垚涓氬姟鍚�',
+  function_name     varchar(50)                                comment '鐢熸垚鍔熻兘鍚�',
+  function_author   varchar(50)                                comment '鐢熸垚鍔熻兘浣滆��',
+  gen_type          char(1)         default '0'                comment '鐢熸垚浠g爜鏂瑰紡锛�0zip鍘嬬缉鍖� 1鑷畾涔夎矾寰勶級',
+  gen_path          varchar(200)    default '/'                comment '鐢熸垚璺緞锛堜笉濉粯璁ら」鐩矾寰勶級',
+  options           varchar(1000)                              comment '鍏跺畠鐢熸垚閫夐」',
+  create_by         varchar(64)     default ''                 comment '鍒涘缓鑰�',
+  create_time 	    datetime                                   comment '鍒涘缓鏃堕棿',
+  update_by         varchar(64)     default ''                 comment '鏇存柊鑰�',
+  update_time       datetime                                   comment '鏇存柊鏃堕棿',
+  remark            varchar(500)    default null               comment '澶囨敞',
+  primary key (table_id)
+) engine=innodb auto_increment=1 comment = '浠g爜鐢熸垚涓氬姟琛�';
+
+
+-- ----------------------------
+-- 19銆佷唬鐮佺敓鎴愪笟鍔¤〃瀛楁
+-- ----------------------------
+drop table if exists gen_table_column;
+create table gen_table_column (
+  column_id         bigint(20)      not null auto_increment    comment '缂栧彿',
+  table_id          bigint(20)                                 comment '褰掑睘琛ㄧ紪鍙�',
+  column_name       varchar(200)                               comment '鍒楀悕绉�',
+  column_comment    varchar(500)                               comment '鍒楁弿杩�',
+  column_type       varchar(100)                               comment '鍒楃被鍨�',
+  java_type         varchar(500)                               comment 'JAVA绫诲瀷',
+  java_field        varchar(200)                               comment 'JAVA瀛楁鍚�',
+  is_pk             char(1)                                    comment '鏄惁涓婚敭锛�1鏄級',
+  is_increment      char(1)                                    comment '鏄惁鑷锛�1鏄級',
+  is_required       char(1)                                    comment '鏄惁蹇呭~锛�1鏄級',
+  is_insert         char(1)                                    comment '鏄惁涓烘彃鍏ュ瓧娈碉紙1鏄級',
+  is_edit           char(1)                                    comment '鏄惁缂栬緫瀛楁锛�1鏄級',
+  is_list           char(1)                                    comment '鏄惁鍒楄〃瀛楁锛�1鏄級',
+  is_query          char(1)                                    comment '鏄惁鏌ヨ瀛楁锛�1鏄級',
+  query_type        varchar(200)    default 'EQ'               comment '鏌ヨ鏂瑰紡锛堢瓑浜庛�佷笉绛変簬銆佸ぇ浜庛�佸皬浜庛�佽寖鍥达級',
+  html_type         varchar(200)                               comment '鏄剧ず绫诲瀷锛堟枃鏈銆佹枃鏈煙銆佷笅鎷夋銆佸閫夋銆佸崟閫夋銆佹棩鏈熸帶浠讹級',
+  dict_type         varchar(200)    default ''                 comment '瀛楀吀绫诲瀷',
+  sort              int                                        comment '鎺掑簭',
+  create_by         varchar(64)     default ''                 comment '鍒涘缓鑰�',
+  create_time 	    datetime                                   comment '鍒涘缓鏃堕棿',
+  update_by         varchar(64)     default ''                 comment '鏇存柊鑰�',
+  update_time       datetime                                   comment '鏇存柊鏃堕棿',
+  primary key (column_id)
+) engine=innodb auto_increment=1 comment = '浠g爜鐢熸垚涓氬姟琛ㄥ瓧娈�';
\ No newline at end of file

--
Gitblit v1.9.3